Browse Source

Merge branch 'main' into median-filter

pull/2219/head
James Jackson-South 3 years ago
committed by GitHub
parent
commit
c359b53ed9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 30
      .editorconfig
  2. 2
      shared-infrastructure
  3. 4
      src/Directory.Build.props
  4. 7
      src/ImageSharp.ruleset
  5. 21
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  6. 5
      src/ImageSharp/Advanced/PreserveAttribute.cs
  7. 13
      src/ImageSharp/Color/Color.cs
  8. 60
      src/ImageSharp/ColorSpaces/CieLab.cs
  9. 66
      src/ImageSharp/ColorSpaces/CieLch.cs
  10. 62
      src/ImageSharp/ColorSpaces/CieLchuv.cs
  11. 58
      src/ImageSharp/ColorSpaces/CieLuv.cs
  12. 46
      src/ImageSharp/ColorSpaces/CieXyy.cs
  13. 48
      src/ImageSharp/ColorSpaces/CieXyz.cs
  14. 60
      src/ImageSharp/ColorSpaces/Cmyk.cs
  15. 21
      src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs
  16. 4
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs
  17. 27
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs
  18. 7
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs
  19. 29
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs
  20. 24
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs
  21. 56
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs
  22. 30
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs
  23. 50
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs
  24. 50
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs
  25. 50
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs
  26. 2
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs
  27. 61
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs
  28. 2
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs
  29. 60
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
  30. 54
      src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs
  31. 46
      src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs
  32. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs
  33. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs
  34. 8
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
  35. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs
  36. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs
  37. 4
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
  38. 8
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs
  39. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs
  40. 10
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs
  41. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs
  42. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs
  43. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
  44. 19
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs
  45. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs
  46. 8
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs
  47. 8
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs
  48. 8
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs
  49. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs
  50. 48
      src/ImageSharp/ColorSpaces/Hsl.cs
  51. 48
      src/ImageSharp/ColorSpaces/Hsv.cs
  52. 58
      src/ImageSharp/ColorSpaces/HunterLab.cs
  53. 56
      src/ImageSharp/ColorSpaces/LinearRgb.cs
  54. 48
      src/ImageSharp/ColorSpaces/Lms.cs
  55. 60
      src/ImageSharp/ColorSpaces/Rgb.cs
  56. 46
      src/ImageSharp/ColorSpaces/YCbCr.cs
  57. 35
      src/ImageSharp/Common/Extensions/EncoderExtensions.cs
  58. 46
      src/ImageSharp/Common/Extensions/StreamExtensions.cs
  59. 2
      src/ImageSharp/Common/Helpers/HexConverter.cs
  60. 6
      src/ImageSharp/Common/Helpers/InliningOptions.cs
  61. 146
      src/ImageSharp/Common/Helpers/Numerics.cs
  62. 32
      src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs
  63. 46
      src/ImageSharp/Common/Helpers/RuntimeUtility.cs
  64. 7
      src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
  65. 216
      src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs
  66. 35
      src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs
  67. 20
      src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
  68. 88
      src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
  69. 26
      src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs
  70. 18
      src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs
  71. 19
      src/ImageSharp/Common/Helpers/SimdUtils.cs
  72. 3
      src/ImageSharp/Common/Helpers/UnitConverter.cs
  73. 22
      src/ImageSharp/Compression/Zlib/Adler32.cs
  74. 16
      src/ImageSharp/Compression/Zlib/Crc32.cs
  75. 6
      src/ImageSharp/Compression/Zlib/DeflaterEngine.cs
  76. 4
      src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs
  77. 2
      src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs
  78. 2
      src/ImageSharp/Configuration.cs
  79. 7
      src/ImageSharp/Diagnostics/MemoryDiagnostics.cs
  80. 37
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  81. 51
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  82. 25
      src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
  83. 4
      src/ImageSharp/Formats/DecoderOptions.cs
  84. 27
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  85. 2
      src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs
  86. 2
      src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs
  87. 4
      src/ImageSharp/Formats/Gif/Sections/GifXmpApplicationExtension.cs
  88. 2
      src/ImageSharp/Formats/ImageFormatManager.cs
  89. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8.Intrinsic.cs
  90. 68
      src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs
  91. 4
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs
  92. 148
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  93. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs
  94. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs
  95. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbAvx.cs
  96. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs
  97. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKAvx.cs
  98. 2
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterAvx.cs
  99. 14
      src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs
  100. 25
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs

30
.editorconfig

@ -1,5 +1,5 @@
# Version: 2.1.0 (Using https://semver.org/)
# Updated: 2021-03-03
# Version: 4.1.1 (Using https://semver.org/)
# Updated: 2022-05-23
# See https://github.com/RehanSaeed/EditorConfig/releases for release notes.
# See https://github.com/RehanSaeed/EditorConfig for updates to this file.
# See http://EditorConfig.org for more information about .editorconfig files.
@ -49,11 +49,11 @@ indent_size = 2
indent_size = 2
# Markdown Files
[*.md]
[*.{md,mdx}]
trim_trailing_whitespace = false
# Web Files
[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}]
[*.{htm,html,js,jsm,ts,tsx,cjs,cts,ctsx,mjs,mts,mtsx,css,sass,scss,less,pcss,svg,vue}]
indent_size = 2
# Batch Files
@ -75,7 +75,7 @@ indent_style = tab
[*.{cs,csx,cake,vb,vbx}]
# Default Severity for all .NET Code Style rules below
dotnet_analyzer_diagnostic.category-style.severity = warning
dotnet_analyzer_diagnostic.severity = warning
##########################################
# Language Rules
@ -128,14 +128,15 @@ file_header_template = Copyright (c) Six Labors.\nLicensed under the Six Labors
# dotnet_diagnostic.SA1636.severity = none
# Undocumented
dotnet_style_operator_placement_when_wrapping = end_of_line
dotnet_style_operator_placement_when_wrapping = end_of_line:warning
csharp_style_prefer_null_check_over_type_check = true:warning
# C# Style Rules
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules
[*.{cs,csx,cake}]
# 'var' preferences
csharp_style_var_for_built_in_types = never
csharp_style_var_when_type_is_apparent = true:warning
csharp_style_var_for_built_in_types = false:warning
csharp_style_var_when_type_is_apparent = false:warning
csharp_style_var_elsewhere = false:warning
# Expression-bodied members
csharp_style_expression_bodied_methods = true:warning
@ -200,12 +201,15 @@ dotnet_diagnostic.IDE0059.severity = suggestion
# Organize using directives
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = false
# Dotnet namespace options
dotnet_style_namespace_match_folder = true:suggestion
dotnet_diagnostic.IDE0130.severity = suggestion
# C# formatting rules
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#c-formatting-rules
[*.{cs,csx,cake}]
# Newline options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#new-line-options
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
@ -214,7 +218,7 @@ csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#indentation-options
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = no_change
@ -222,7 +226,7 @@ csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents_when_block = false
# Spacing options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#spacing-options
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_between_parentheses = false
@ -246,7 +250,7 @@ csharp_space_before_open_square_brackets = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_square_brackets = false
# Wrap options
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options
# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#wrap-options
csharp_preserve_single_line_statements = false
csharp_preserve_single_line_blocks = true
@ -448,4 +452,4 @@ dotnet_naming_rule.parameters_rule.severity = warning
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
##########################################
##########################################

2
shared-infrastructure

@ -1 +1 @@
Subproject commit c0e0353c1ee89398def0ccdc3e945380034fbea8
Subproject commit 5eb77e2d9eb4f0ece012c996941ab78db1af2a41

4
src/Directory.Build.props

@ -21,6 +21,10 @@
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
<CodeAnalysisRuleSet>..\ImageSharp.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<!-- DynamicProxyGenAssembly2 is needed so Moq can use our internals -->
<InternalsVisibleTo Include="DynamicProxyGenAssembly2" Key="0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" />

7
src/ImageSharp.ruleset

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="ImageSharp" ToolsVersion="17.0">
<Include Path="..\shared-infrastructure\sixlabors.ruleset" Action="Default" />
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1011" Action="None" />
</Rules>
</RuleSet>

21
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading;
@ -34,11 +35,11 @@ namespace SixLabors.ImageSharp.Advanced
IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext);
if (format is null)
{
var sb = new StringBuilder();
sb.AppendLine($"No encoder was found for extension '{ext}'. Registered encoders include:");
StringBuilder sb = new();
sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}'. Registered encoders include:");
foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats)
{
sb.AppendFormat(" - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine);
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine);
}
throw new NotSupportedException(sb.ToString());
@ -48,11 +49,11 @@ namespace SixLabors.ImageSharp.Advanced
if (encoder is null)
{
var sb = new StringBuilder();
sb.AppendLine($"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
StringBuilder sb = new();
sb.AppendLine(CultureInfo.InvariantCulture, $"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
foreach (KeyValuePair<IImageFormat, IImageEncoder> enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
sb.AppendFormat(" - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
sb.AppendFormat(CultureInfo.InvariantCulture, " - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
}
throw new NotSupportedException(sb.ToString());
@ -116,6 +117,7 @@ namespace SixLabors.ImageSharp.Advanced
/// Certain Image Processors may invalidate the returned <see cref="IMemoryGroup{T}"/> and all it's buffers,
/// therefore it's not recommended to mutate the image while holding a reference to it's <see cref="IMemoryGroup{T}"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="source"/> in <see langword="null"/>.</exception>
public static IMemoryGroup<TPixel> GetPixelMemoryGroup<TPixel>(this ImageFrame<TPixel> source)
where TPixel : unmanaged, IPixel<TPixel>
=> source?.PixelBuffer.FastMemoryGroup.View ?? throw new ArgumentNullException(nameof(source));
@ -131,13 +133,14 @@ namespace SixLabors.ImageSharp.Advanced
/// Certain Image Processors may invalidate the returned <see cref="IMemoryGroup{T}"/> and all it's buffers,
/// therefore it's not recommended to mutate the image while holding a reference to it's <see cref="IMemoryGroup{T}"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">Thrown when the <paramref name="source"/> in <see langword="null"/>.</exception>
public static IMemoryGroup<TPixel> GetPixelMemoryGroup<TPixel>(this Image<TPixel> source)
where TPixel : unmanaged, IPixel<TPixel>
=> source?.Frames.RootFrame.GetPixelMemoryGroup() ?? throw new ArgumentNullException(nameof(source));
/// <summary>
/// Gets the representation of the pixels as a <see cref="Span{T}"/> of contiguous memory
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
/// at row <paramref name="rowIndex"/> beginning from the first pixel on that row.
/// </summary>
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
/// <param name="source">The source.</param>
@ -154,8 +157,8 @@ namespace SixLabors.ImageSharp.Advanced
}
/// <summary>
/// Gets the representation of the pixels as <see cref="Span{T}"/> of of contiguous memory
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
/// Gets the representation of the pixels as <see cref="Span{T}"/> of contiguous memory
/// at row <paramref name="rowIndex"/> beginning from the first pixel on that row.
/// </summary>
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
/// <param name="source">The source.</param>

5
src/ImageSharp/Advanced/PreserveAttribute.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
namespace SixLabors.ImageSharp.Advanced
{
/// <summary>
@ -8,7 +10,8 @@ namespace SixLabors.ImageSharp.Advanced
/// The only thing that matters is the class name.
/// There is no need to use or inherit from the PreserveAttribute class in each environment.
/// </summary>
internal sealed class PreserveAttribute : System.Attribute
[AttributeUsage(AttributeTargets.Method)]
internal sealed class PreserveAttribute : Attribute
{
}
}

13
src/ImageSharp/Color/Color.cs

@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(InliningOptions.ShortMethod)]
public static Color ParseHex(string hex)
{
var rgba = Rgba32.ParseHex(hex);
Rgba32 rgba = Rgba32.ParseHex(hex);
return new Color(rgba);
}
@ -193,6 +193,7 @@ namespace SixLabors.ImageSharp
/// <returns>
/// The <see cref="Color"/>.
/// </returns>
/// <exception cref="ArgumentException">Input string is not in the correct format.</exception>
public static Color Parse(string input)
{
Guard.NotNull(input, nameof(input));
@ -241,7 +242,7 @@ namespace SixLabors.ImageSharp
/// <returns>The color having it's alpha channel altered.</returns>
public Color WithAlpha(float alpha)
{
var v = (Vector4)this;
Vector4 v = (Vector4)this;
v.W = alpha;
return new Color(v);
}
@ -290,12 +291,12 @@ namespace SixLabors.ImageSharp
/// <param name="source">The source color span.</param>
/// <param name="destination">The destination pixel span.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToPixel<TPixel>(
Configuration configuration,
ReadOnlySpan<Color> source,
Span<TPixel> destination)
#pragma warning disable RCS1163 // Unused parameter.
public static void ToPixel<TPixel>(Configuration configuration, ReadOnlySpan<Color> source, Span<TPixel> destination)
#pragma warning restore RCS1163 // Unused parameter.
where TPixel : unmanaged, IPixel<TPixel>
{
// TODO: Investigate bulk operations utilizing configuration parameter here.
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
for (int i = 0; i < source.Length; i++)
{

60
src/ImageSharp/ColorSpaces/CieLab.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -19,29 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public static readonly CieXyz DefaultWhitePoint = Illuminants.D50;
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L;
/// <summary>
/// Gets the a color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
/// </summary>
public readonly float A;
/// <summary>
/// Gets the b color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
/// </summary>
public readonly float B;
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint;
/// <summary>
/// Initializes a new instance of the <see cref="CieLab"/> struct.
/// </summary>
@ -95,6 +72,29 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.WhitePoint = whitePoint;
}
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L { get; }
/// <summary>
/// Gets the a color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
/// </summary>
public readonly float A { get; }
/// <summary>
/// Gets the b color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
/// </summary>
public readonly float B { get; }
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint { get; }
/// <summary>
/// Compares two <see cref="CieLab"/> objects for equality.
/// </summary>
@ -128,12 +128,10 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieLab other)
{
return this.L.Equals(other.L)
&& this.A.Equals(other.A)
&& this.B.Equals(other.B)
&& this.WhitePoint.Equals(other.WhitePoint);
}
public bool Equals(CieLab other) =>
this.L.Equals(other.L)
&& this.A.Equals(other.A)
&& this.B.Equals(other.B)
&& this.WhitePoint.Equals(other.WhitePoint);
}
}

66
src/ImageSharp/ColorSpaces/CieLch.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -19,31 +19,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public static readonly CieXyz DefaultWhitePoint = Illuminants.D50;
private static readonly Vector3 Min = new Vector3(0, -200, 0);
private static readonly Vector3 Max = new Vector3(100, 200, 360);
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L;
/// <summary>
/// Gets the a chroma component.
/// <remarks>A value ranging from 0 to 200.</remarks>
/// </summary>
public readonly float C;
/// <summary>
/// Gets the h° hue component in degrees.
/// <remarks>A value ranging from 0 to 360.</remarks>
/// </summary>
public readonly float H;
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint;
private static readonly Vector3 Min = new(0, -200, 0);
private static readonly Vector3 Max = new(100, 200, 360);
/// <summary>
/// Initializes a new instance of the <see cref="CieLch"/> struct.
@ -97,6 +74,29 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.WhitePoint = whitePoint;
}
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L { get; }
/// <summary>
/// Gets the a chroma component.
/// <remarks>A value ranging from 0 to 200.</remarks>
/// </summary>
public readonly float C { get; }
/// <summary>
/// Gets the h° hue component in degrees.
/// <remarks>A value ranging from 0 to 360.</remarks>
/// </summary>
public readonly float H { get; }
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint { get; }
/// <summary>
/// Compares two <see cref="CieLch"/> objects for equality.
/// </summary>
@ -121,9 +121,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(this.L, this.C, this.H, this.WhitePoint);
}
=> HashCode.Combine(this.L, this.C, this.H, this.WhitePoint);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieLch({this.L:#0.##}, {this.C:#0.##}, {this.H:#0.##})");
@ -135,12 +133,10 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieLch other)
{
return this.L.Equals(other.L)
&& this.C.Equals(other.C)
&& this.H.Equals(other.H)
&& this.WhitePoint.Equals(other.WhitePoint);
}
=> this.L.Equals(other.L)
&& this.C.Equals(other.C)
&& this.H.Equals(other.H)
&& this.WhitePoint.Equals(other.WhitePoint);
/// <summary>
/// Computes the saturation of the color (chroma normalized by lightness)

62
src/ImageSharp/ColorSpaces/CieLchuv.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -13,8 +13,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public readonly struct CieLchuv : IEquatable<CieLchuv>
{
private static readonly Vector3 Min = new Vector3(0, -200, 0);
private static readonly Vector3 Max = new Vector3(100, 200, 360);
private static readonly Vector3 Min = new(0, -200, 0);
private static readonly Vector3 Max = new(100, 200, 360);
/// <summary>
/// D50 standard illuminant.
@ -22,29 +22,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65;
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L;
/// <summary>
/// Gets the a chroma component.
/// <remarks>A value ranging from 0 to 200.</remarks>
/// </summary>
public readonly float C;
/// <summary>
/// Gets the h° hue component in degrees.
/// <remarks>A value ranging from 0 to 360.</remarks>
/// </summary>
public readonly float H;
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint;
/// <summary>
/// Initializes a new instance of the <see cref="CieLchuv"/> struct.
/// </summary>
@ -98,6 +75,29 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.WhitePoint = whitePoint;
}
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L { get; }
/// <summary>
/// Gets the a chroma component.
/// <remarks>A value ranging from 0 to 200.</remarks>
/// </summary>
public readonly float C { get; }
/// <summary>
/// Gets the h° hue component in degrees.
/// <remarks>A value ranging from 0 to 360.</remarks>
/// </summary>
public readonly float H { get; }
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint { get; }
/// <summary>
/// Compares two <see cref="CieLchuv"/> objects for equality.
/// </summary>
@ -130,12 +130,10 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieLchuv other)
{
return this.L.Equals(other.L)
&& this.C.Equals(other.C)
&& this.H.Equals(other.H)
&& this.WhitePoint.Equals(other.WhitePoint);
}
=> this.L.Equals(other.L)
&& this.C.Equals(other.C)
&& this.H.Equals(other.H)
&& this.WhitePoint.Equals(other.WhitePoint);
/// <summary>
/// Computes the saturation of the color (chroma normalized by lightness)

58
src/ImageSharp/ColorSpaces/CieLuv.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -21,29 +21,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public static readonly CieXyz DefaultWhitePoint = Illuminants.D65;
/// <summary>
/// Gets the lightness dimension
/// <remarks>A value usually ranging between 0 and 100.</remarks>
/// </summary>
public readonly float L;
/// <summary>
/// Gets the blue-yellow chromaticity coordinate of the given whitepoint.
/// <remarks>A value usually ranging between -100 and 100.</remarks>
/// </summary>
public readonly float U;
/// <summary>
/// Gets the red-green chromaticity coordinate of the given whitepoint.
/// <remarks>A value usually ranging between -100 and 100.</remarks>
/// </summary>
public readonly float V;
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint;
/// <summary>
/// Initializes a new instance of the <see cref="CieLuv"/> struct.
/// </summary>
@ -96,6 +73,29 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.WhitePoint = whitePoint;
}
/// <summary>
/// Gets the lightness dimension
/// <remarks>A value usually ranging between 0 and 100.</remarks>
/// </summary>
public readonly float L { get; }
/// <summary>
/// Gets the blue-yellow chromaticity coordinate of the given whitepoint.
/// <remarks>A value usually ranging between -100 and 100.</remarks>
/// </summary>
public readonly float U { get; }
/// <summary>
/// Gets the red-green chromaticity coordinate of the given whitepoint.
/// <remarks>A value usually ranging between -100 and 100.</remarks>
/// </summary>
public readonly float V { get; }
/// <summary>
/// Gets the reference white point of this color
/// </summary>
public readonly CieXyz WhitePoint { get; }
/// <summary>
/// Compares two <see cref="CieLuv"/> objects for equality.
/// </summary>
@ -130,11 +130,9 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieLuv other)
{
return this.L.Equals(other.L)
&& this.U.Equals(other.U)
&& this.V.Equals(other.V)
&& this.WhitePoint.Equals(other.WhitePoint);
}
=> this.L.Equals(other.L)
&& this.U.Equals(other.U)
&& this.V.Equals(other.V)
&& this.WhitePoint.Equals(other.WhitePoint);
}
}

46
src/ImageSharp/ColorSpaces/CieXyy.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -13,24 +13,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public readonly struct CieXyy : IEquatable<CieXyy>
{
/// <summary>
/// Gets the X chrominance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float X;
/// <summary>
/// Gets the Y chrominance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Y;
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Yl;
/// <summary>
/// Initializes a new instance of the <see cref="CieXyy"/> struct.
/// </summary>
@ -60,6 +42,24 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.Yl = vector.Z;
}
/// <summary>
/// Gets the X chrominance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float X { get; }
/// <summary>
/// Gets the Y chrominance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Y { get; }
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Yl { get; }
/// <summary>
/// Compares two <see cref="CieXyy"/> objects for equality.
/// </summary>
@ -94,10 +94,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieXyy other)
{
return this.X.Equals(other.X)
&& this.Y.Equals(other.Y)
&& this.Yl.Equals(other.Yl);
}
=> this.X.Equals(other.X)
&& this.Y.Equals(other.Y)
&& this.Yl.Equals(other.Yl);
}
}

48
src/ImageSharp/ColorSpaces/CieXyz.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -13,24 +13,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public readonly struct CieXyz : IEquatable<CieXyz>
{
/// <summary>
/// Gets the X component. A mix (a linear combination) of cone response curves chosen to be nonnegative.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float X;
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Y;
/// <summary>
/// Gets the Z component. Quasi-equal to blue stimulation, or the S cone response.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Z;
/// <summary>
/// Initializes a new instance of the <see cref="CieXyz"/> struct.
/// </summary>
@ -56,6 +38,24 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.Z = vector.Z;
}
/// <summary>
/// Gets the X component. A mix (a linear combination) of cone response curves chosen to be nonnegative.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float X { get; }
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Y { get; }
/// <summary>
/// Gets the Z component. Quasi-equal to blue stimulation, or the S cone response.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Z { get; }
/// <summary>
/// Compares two <see cref="CieXyz"/> objects for equality.
/// </summary>
@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
/// <returns>The <see cref="Vector3"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector3 ToVector3() => new Vector3(this.X, this.Y, this.Z);
public Vector3 ToVector3() => new(this.X, this.Y, this.Z);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.X, this.Y, this.Z);
@ -97,10 +97,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieXyz other)
{
return this.X.Equals(other.X)
&& this.Y.Equals(other.Y)
&& this.Z.Equals(other.Z);
}
=> this.X.Equals(other.X)
&& this.Y.Equals(other.Y)
&& this.Z.Equals(other.Z);
}
}

60
src/ImageSharp/ColorSpaces/Cmyk.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -15,30 +15,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
private static readonly Vector4 Min = Vector4.Zero;
private static readonly Vector4 Max = Vector4.One;
/// <summary>
/// Gets the cyan color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float C;
/// <summary>
/// Gets the magenta color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float M;
/// <summary>
/// Gets the yellow color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Y;
/// <summary>
/// Gets the keyline black color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float K;
/// <summary>
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
/// </summary>
@ -66,6 +42,30 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.K = vector.W;
}
/// <summary>
/// Gets the cyan color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float C { get; }
/// <summary>
/// Gets the magenta color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float M { get; }
/// <summary>
/// Gets the yellow color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float Y { get; }
/// <summary>
/// Gets the keyline black color component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float K { get; }
/// <summary>
/// Compares two <see cref="Cmyk"/> objects for equality.
/// </summary>
@ -101,11 +101,9 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Cmyk other)
{
return this.C.Equals(other.C)
&& this.M.Equals(other.M)
&& this.Y.Equals(other.Y)
&& this.K.Equals(other.K);
}
=> this.C.Equals(other.C)
&& this.M.Equals(other.M)
&& this.Y.Equals(other.Y)
&& this.K.Equals(other.K);
}
}

21
src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs

@ -5,10 +5,8 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
namespace SixLabors.ImageSharp.ColorSpaces.Companding
{
@ -25,10 +23,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
private const int Length = Scale + 2; // 256kb @ 16bit precision.
private const int Scale = (1 << 16) - 1;
private static readonly Lazy<float[]> LazyCompressTable = new Lazy<float[]>(
private static readonly Lazy<float[]> LazyCompressTable = new(
() =>
{
var result = new float[Length];
float[] result = new float[Length];
for (int i = 0; i < result.Length; i++)
{
@ -49,10 +47,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
},
true);
private static readonly Lazy<float[]> LazyExpandTable = new Lazy<float[]>(
private static readonly Lazy<float[]> LazyExpandTable = new(
() =>
{
var result = new float[Length];
float[] result = new float[Length];
for (int i = 0; i < result.Length; i++)
{
@ -84,7 +82,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Expand(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
CompandAvx2(vectors, ExpandTable);
@ -92,11 +89,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
if (Numerics.Modulo2(vectors.Length) != 0)
{
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
Expand(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
Expand(ref MemoryMarshal.GetReference(vectors[^1..]));
}
}
else
#endif
{
CompandScalar(vectors, ExpandTable);
}
@ -109,7 +105,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Compress(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
CompandAvx2(vectors, CompressTable);
@ -117,11 +112,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
if (Numerics.Modulo2(vectors.Length) != 0)
{
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
Compress(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
Compress(ref MemoryMarshal.GetReference(vectors[^1..]));
}
}
else
#endif
{
CompandScalar(vectors, CompressTable);
}
@ -171,8 +165,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
public static float Compress(float channel)
=> channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F;
#if SUPPORTS_RUNTIME_INTRINSICS
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void CompandAvx2(Span<Vector4> vectors, float[] table)
{
@ -204,7 +196,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
}
}
}
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void CompandScalar(Span<Vector4> vectors, float[] table)

4
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs

@ -150,9 +150,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
return color;
}
var linearInput = this.ToLinearRgb(color);
var linearInput = ToLinearRgb(color);
LinearRgb linearOutput = this.Adapt(linearInput);
return this.ToRgb(linearOutput);
return ToRgb(linearOutput);
}
}
}

27
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLab.cs

@ -12,11 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
/// <summary>
/// The converter for converting between CieLch to CieLab.
/// </summary>
private static readonly CieLchToCieLabConverter CieLchToCieLabConverter = new CieLchToCieLabConverter();
/// <summary>
/// Converts a <see cref="CieLch"/> into a <see cref="CieLab"/>.
/// </summary>
@ -58,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -91,7 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -124,7 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -190,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -222,7 +217,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in Hsl color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -255,7 +250,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -287,7 +282,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -320,7 +315,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -353,7 +348,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -386,7 +381,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}
@ -419,7 +414,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLab"/></returns>
public CieLab ToCieLab(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLab(xyzColor);
}

7
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLch.cs

@ -12,11 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
/// <summary>
/// The converter for converting between CieLab to CieLch.
/// </summary>
private static readonly CieLabToCieLchConverter CieLabToCieLchConverter = new CieLabToCieLchConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="CieLch"/>
/// </summary>
@ -123,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLch"/></returns>
public CieLch ToCieLch(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
var xyzColor = ToCieXyz(color);
return this.ToCieLch(xyzColor);
}

29
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLchuv.cs

@ -12,11 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
/// <summary>
/// The converter for converting between CieLab to CieLchuv.
/// </summary>
private static readonly CieLuvToCieLchuvConverter CieLuvToCieLchuvConverter = new CieLuvToCieLchuvConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="CieLchuv"/>
/// </summary>
@ -24,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -57,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -123,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -156,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in CieXyz color)
{
var luvColor = this.ToCieLuv(color);
CieLuv luvColor = this.ToCieLuv(color);
return this.ToCieLchuv(luvColor);
}
@ -189,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -222,7 +217,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in Hsl color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -255,7 +250,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -288,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -321,7 +316,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -354,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -387,7 +382,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}
@ -420,7 +415,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLchuv"/></returns>
public CieLchuv ToCieLchuv(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLchuv(xyzColor);
}

24
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieLuv.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly CieLchuvToCieLuvConverter CieLchuvToCieLuvConverter = new CieLchuvToCieLuvConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="CieLuv"/>.
/// </summary>
@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -53,7 +51,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -187,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -219,7 +217,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in Hsl color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -251,7 +249,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -283,7 +281,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -315,7 +313,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -347,7 +345,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -379,7 +377,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}
@ -411,7 +409,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieLuv"/></returns>
public CieLuv ToCieLuv(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieLuv(xyzColor);
}

56
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyy.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly CieXyzAndCieXyyConverter CieXyzAndCieXyyConverter = new CieXyzAndCieXyyConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="CieXyy"/>
/// </summary>
@ -21,9 +19,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -54,9 +52,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -87,9 +85,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -120,9 +118,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -151,14 +149,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in CieXyz color) => CieXyzAndCieXyyConverter.Convert(color);
public static CieXyy ToCieXyy(in CieXyz color) => CieXyzAndCieXyyConverter.Convert(color);
/// <summary>
/// Performs the bulk conversion from <see cref="CieXyz"/> into <see cref="CieXyy"/>
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<CieXyz> source, Span<CieXyy> destination)
public static void Convert(ReadOnlySpan<CieXyz> source, Span<CieXyy> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -170,7 +168,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref CieXyz sp = ref Unsafe.Add(ref sourceRef, i);
ref CieXyy dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToCieXyy(sp);
dp = ToCieXyy(sp);
}
}
@ -181,9 +179,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in Cmyk color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -214,9 +212,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(Hsl color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -247,9 +245,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in Hsv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -280,9 +278,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -313,9 +311,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in LinearRgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -346,9 +344,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -379,9 +377,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in Rgb color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>
@ -412,9 +410,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyy"/></returns>
public CieXyy ToCieXyy(in YCbCr color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCieXyy(xyzColor);
return ToCieXyy(xyzColor);
}
/// <summary>

30
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs

@ -12,12 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly CieLabToCieXyzConverter CieLabToCieXyzConverter = new CieLabToCieXyzConverter();
private static readonly CieLuvToCieXyzConverter CieLuvToCieXyzConverter = new CieLuvToCieXyzConverter();
private static readonly HunterLabToCieXyzConverter
HunterLabToCieXyzConverter = new HunterLabToCieXyzConverter();
private static readonly HunterLabToCieXyzConverter HunterLabToCieXyzConverter = new();
private LinearRgbToCieXyzConverter linearRgbToCieXyzConverter;
@ -166,18 +161,17 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="CieXyz"/></returns>
public CieXyz ToCieXyz(in CieXyy color)
{
public static CieXyz ToCieXyz(in CieXyy color)
// Conversion
return CieXyzAndCieXyyConverter.Convert(color);
}
=> CieXyzAndCieXyyConverter.Convert(color);
/// <summary>
/// Performs the bulk conversion from <see cref="CieXyy"/> into <see cref="CieXyz"/>.
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<CieXyy> source, Span<CieXyz> destination)
public static void Convert(ReadOnlySpan<CieXyy> source, Span<CieXyz> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -189,7 +183,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref CieXyy sp = ref Unsafe.Add(ref sourceRef, i);
ref CieXyz dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToCieXyz(sp);
dp = ToCieXyz(sp);
}
}
@ -200,7 +194,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyz"/></returns>
public CieXyz ToCieXyz(in Cmyk color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return this.ToCieXyz(rgb);
}
@ -233,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyz"/></returns>
public CieXyz ToCieXyz(in Hsl color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return this.ToCieXyz(rgb);
}
@ -267,7 +261,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public CieXyz ToCieXyz(in Hsv color)
{
// Conversion
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return this.ToCieXyz(rgb);
}
@ -367,9 +361,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="CieXyz"/></returns>
public CieXyz ToCieXyz(in Lms color)
{
return this.cieXyzAndLmsConverter.Convert(color);
}
=> this.cieXyzAndLmsConverter.Convert(color);
/// <summary>
/// Performs the bulk conversion from <see cref="Lms"/> into <see cref="CieXyz"/>.
@ -432,7 +424,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="CieXyz"/></returns>
public CieXyz ToCieXyz(in YCbCr color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return this.ToCieXyz(rgb);
}

50
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Cmyk.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly CmykAndRgbConverter CmykAndRgbConverter = new CmykAndRgbConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="Cmyk"/>.
/// </summary>
@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
}
@ -54,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
}
@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
}
@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
}
@ -153,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToCmyk(xyzColor);
}
@ -186,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in CieXyz color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
}
@ -217,9 +215,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in Hsl color)
public static Cmyk ToCmyk(in Hsl color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
}
@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Hsl> source, Span<Cmyk> destination)
public static void Convert(ReadOnlySpan<Hsl> source, Span<Cmyk> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i);
ref Cmyk dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToCmyk(sp);
dp = ToCmyk(sp);
}
}
@ -250,9 +248,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in Hsv color)
public static Cmyk ToCmyk(in Hsv color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
}
@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Hsv> source, Span<Cmyk> destination)
public static void Convert(ReadOnlySpan<Hsv> source, Span<Cmyk> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -274,7 +272,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i);
ref Cmyk dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToCmyk(sp);
dp = ToCmyk(sp);
}
}
@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
}
@ -316,9 +314,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in LinearRgb color)
public static Cmyk ToCmyk(in LinearRgb color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
}
@ -328,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<LinearRgb> source, Span<Cmyk> destination)
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Cmyk> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -340,7 +338,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i);
ref Cmyk dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToCmyk(sp);
dp = ToCmyk(sp);
}
}
@ -351,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToCmyk(xyzColor);
}
@ -382,14 +380,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in Rgb color) => CmykAndRgbConverter.Convert(color);
public static Cmyk ToCmyk(in Rgb color) => CmykAndRgbConverter.Convert(color);
/// <summary>
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="Cmyk"/>
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Rgb> source, Span<Cmyk> destination)
public static void Convert(ReadOnlySpan<Rgb> source, Span<Cmyk> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -401,7 +399,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i);
ref Cmyk dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToCmyk(sp);
dp = ToCmyk(sp);
}
}
@ -412,7 +410,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Cmyk"/></returns>
public Cmyk ToCmyk(in YCbCr color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return CmykAndRgbConverter.Convert(rgb);
}

50
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsl.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly HslAndRgbConverter HslAndRgbConverter = new HslAndRgbConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="Hsl"/>.
/// </summary>
@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
@ -54,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
@ -153,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToHsl(xyzColor);
}
@ -186,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in CieXyz color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}
@ -217,9 +215,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in Cmyk color)
public static Hsl ToHsl(in Cmyk color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}
@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Cmyk> source, Span<Hsl> destination)
public static void Convert(ReadOnlySpan<Cmyk> source, Span<Hsl> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsl dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsl(sp);
dp = ToHsl(sp);
}
}
@ -250,9 +248,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in Hsv color)
public static Hsl ToHsl(in Hsv color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}
@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Hsv> source, Span<Hsl> destination)
public static void Convert(ReadOnlySpan<Hsv> source, Span<Hsl> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -274,7 +272,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsl dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsl(sp);
dp = ToHsl(sp);
}
}
@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
@ -316,9 +314,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in LinearRgb color)
public static Hsl ToHsl(in LinearRgb color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}
@ -328,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<LinearRgb> source, Span<Hsl> destination)
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Hsl> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -340,7 +338,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsl dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsl(sp);
dp = ToHsl(sp);
}
}
@ -351,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsl(xyzColor);
}
@ -382,14 +380,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in Rgb color) => HslAndRgbConverter.Convert(color);
public static Hsl ToHsl(in Rgb color) => HslAndRgbConverter.Convert(color);
/// <summary>
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="Hsl"/>.
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Rgb> source, Span<Hsl> destination)
public static void Convert(ReadOnlySpan<Rgb> source, Span<Hsl> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -401,7 +399,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsl dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsl(sp);
dp = ToHsl(sp);
}
}
@ -412,7 +410,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsl"/></returns>
public Hsl ToHsl(in YCbCr color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return HslAndRgbConverter.Convert(rgb);
}

50
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Hsv.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly HsvAndRgbConverter HsvAndRgbConverter = new HsvAndRgbConverter();
/// <summary>
/// Converts a <see cref="CieLab"/> into a <see cref="Hsv"/>
/// </summary>
@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsv(xyzColor);
}
@ -54,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsv(xyzColor);
}
@ -87,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsv(xyzColor);
}
@ -120,7 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsv(xyzColor);
}
@ -153,7 +151,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToHsv(xyzColor);
}
@ -186,7 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in CieXyz color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return HsvAndRgbConverter.Convert(rgb);
}
@ -217,9 +215,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in Cmyk color)
public static Hsv ToHsv(in Cmyk color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return HsvAndRgbConverter.Convert(rgb);
}
@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Cmyk> source, Span<Hsv> destination)
public static void Convert(ReadOnlySpan<Cmyk> source, Span<Hsv> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsv dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsv(sp);
dp = ToHsv(sp);
}
}
@ -250,9 +248,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in Hsl color)
public static Hsv ToHsv(in Hsl color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return HsvAndRgbConverter.Convert(rgb);
}
@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors.</param>
public void Convert(ReadOnlySpan<Hsl> source, Span<Hsv> destination)
public static void Convert(ReadOnlySpan<Hsl> source, Span<Hsv> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -274,7 +272,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsv dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsv(sp);
dp = ToHsv(sp);
}
}
@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsv(xyzColor);
}
@ -316,9 +314,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in LinearRgb color)
public static Hsv ToHsv(in LinearRgb color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return HsvAndRgbConverter.Convert(rgb);
}
@ -328,7 +326,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<LinearRgb> source, Span<Hsv> destination)
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Hsv> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -340,7 +338,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsv dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsv(sp);
dp = ToHsv(sp);
}
}
@ -351,7 +349,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToHsv(xyzColor);
}
@ -382,14 +380,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in Rgb color) => HsvAndRgbConverter.Convert(color);
public static Hsv ToHsv(in Rgb color) => HsvAndRgbConverter.Convert(color);
/// <summary>
/// Performs the bulk conversion from <see cref="Rgb"/> into <see cref="Hsv"/>
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Rgb> source, Span<Hsv> destination)
public static void Convert(ReadOnlySpan<Rgb> source, Span<Hsv> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -401,7 +399,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i);
ref Hsv dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToHsv(sp);
dp = ToHsv(sp);
}
}
@ -412,7 +410,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Hsv"/></returns>
public Hsv ToHsv(in YCbCr color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return HsvAndRgbConverter.Convert(rgb);
}

2
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.HunterLab.cs

@ -336,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="HunterLab"/></returns>
public HunterLab ToHunterLab(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
var xyzColor = ToCieXyz(color);
return this.ToHunterLab(xyzColor);
}

61
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.LinearRgb.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly RgbToLinearRgbConverter RgbToLinearRgbConverter = new RgbToLinearRgbConverter();
/// <summary>
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="LinearRgb"/>.
/// </summary>
@ -145,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors.</param>
/// <param name="destination">The span to the destination colors.</param>
public void Convert(ReadOnlySpan<Cmyk> source, Span<LinearRgb> destination)
public static void Convert(ReadOnlySpan<Cmyk> source, Span<LinearRgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -157,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i);
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToLinearRgb(sp);
dp = ToLinearRgb(sp);
}
}
@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors.</param>
/// <param name="destination">The span to the destination colors.</param>
public void Convert(ReadOnlySpan<Hsl> source, Span<LinearRgb> destination)
public static void Convert(ReadOnlySpan<Hsl> source, Span<LinearRgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -178,7 +176,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i);
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToLinearRgb(sp);
dp = ToLinearRgb(sp);
}
}
@ -187,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors.</param>
/// <param name="destination">The span to the destination colors.</param>
public void Convert(ReadOnlySpan<Hsv> source, Span<LinearRgb> destination)
public static void Convert(ReadOnlySpan<Hsv> source, Span<LinearRgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i);
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToLinearRgb(sp);
dp = ToLinearRgb(sp);
}
}
@ -250,7 +248,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Rgb> source, Span<LinearRgb> destination)
public static void Convert(ReadOnlySpan<Rgb> source, Span<LinearRgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i);
ref LinearRgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToLinearRgb(sp);
dp = ToLinearRgb(sp);
}
}
@ -294,7 +292,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@ -305,7 +303,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@ -316,7 +314,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@ -327,7 +325,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@ -338,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@ -361,10 +359,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in Cmyk color)
public static LinearRgb ToLinearRgb(in Cmyk color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
Rgb rgb = ToRgb(color);
return ToLinearRgb(rgb);
}
/// <summary>
@ -372,10 +370,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in Hsl color)
public static LinearRgb ToLinearRgb(in Hsl color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
Rgb rgb = ToRgb(color);
return ToLinearRgb(rgb);
}
/// <summary>
@ -383,10 +381,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in Hsv color)
public static LinearRgb ToLinearRgb(in Hsv color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
Rgb rgb = ToRgb(color);
return ToLinearRgb(rgb);
}
/// <summary>
@ -396,7 +394,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@ -407,7 +405,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToLinearRgb(xyzColor);
}
@ -416,11 +414,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in Rgb color)
{
// Conversion
return RgbToLinearRgbConverter.Convert(color);
}
public static LinearRgb ToLinearRgb(in Rgb color)
=> RgbToLinearRgbConverter.Convert(color);
/// <summary>
/// Converts a <see cref="YCbCr"/> into a <see cref="LinearRgb"/>.
@ -429,8 +424,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="LinearRgb"/></returns>
public LinearRgb ToLinearRgb(in YCbCr color)
{
var rgb = this.ToRgb(color);
return this.ToLinearRgb(rgb);
Rgb rgb = this.ToRgb(color);
return ToLinearRgb(rgb);
}
}
}

2
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Lms.cs

@ -336,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Lms"/></returns>
public Lms ToLms(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
var xyzColor = ToCieXyz(color);
return this.ToLms(xyzColor);
}

60
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly LinearRgbToRgbConverter LinearRgbToRgbConverter = new LinearRgbToRgbConverter();
/// <summary>
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="Rgb"/>
/// </summary>
@ -145,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Cmyk> source, Span<Rgb> destination)
public static void Convert(ReadOnlySpan<Cmyk> source, Span<Rgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -157,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToRgb(sp);
dp = ToRgb(sp);
}
}
@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Hsv> source, Span<Rgb> destination)
public static void Convert(ReadOnlySpan<Hsv> source, Span<Rgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -178,7 +176,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToRgb(sp);
dp = ToRgb(sp);
}
}
@ -187,7 +185,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Hsl> source, Span<Rgb> destination)
public static void Convert(ReadOnlySpan<Hsl> source, Span<Rgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -199,7 +197,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToRgb(sp);
dp = ToRgb(sp);
}
}
@ -229,7 +227,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<LinearRgb> source, Span<Rgb> destination)
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<Rgb> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -241,7 +239,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToRgb(sp);
dp = ToRgb(sp);
}
}
@ -294,7 +292,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@ -305,7 +303,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@ -316,7 +314,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in CieLchuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@ -327,7 +325,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@ -338,7 +336,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@ -350,10 +348,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
public Rgb ToRgb(in CieXyz color)
{
// Conversion
var linear = this.ToLinearRgb(color);
LinearRgb linear = this.ToLinearRgb(color);
// Compand
return this.ToRgb(linear);
return ToRgb(linear);
}
/// <summary>
@ -361,33 +359,21 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in Cmyk color)
{
// Conversion
return CmykAndRgbConverter.Convert(color);
}
public static Rgb ToRgb(in Cmyk color) => CmykAndRgbConverter.Convert(color);
/// <summary>
/// Converts a <see cref="Hsv"/> into a <see cref="Rgb"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in Hsv color)
{
// Conversion
return HsvAndRgbConverter.Convert(color);
}
public static Rgb ToRgb(in Hsv color) => HsvAndRgbConverter.Convert(color);
/// <summary>
/// Converts a <see cref="Hsl"/> into a <see cref="Rgb"/>
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in Hsl color)
{
// Conversion
return HslAndRgbConverter.Convert(color);
}
public static Rgb ToRgb(in Hsl color) => HslAndRgbConverter.Convert(color);
/// <summary>
/// Converts a <see cref="HunterLab"/> into a <see cref="Rgb"/>
@ -396,7 +382,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}
@ -405,11 +391,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in LinearRgb color)
{
// Conversion
return LinearRgbToRgbConverter.Convert(color);
}
public static Rgb ToRgb(in LinearRgb color) => LinearRgbToRgbConverter.Convert(color);
/// <summary>
/// Converts a <see cref="Lms"/> into a <see cref="Rgb"/>
@ -418,7 +400,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="Rgb"/></returns>
public Rgb ToRgb(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToRgb(xyzColor);
}

54
src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.YCbCr.cs

@ -12,8 +12,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </content>
public partial class ColorSpaceConverter
{
private static readonly YCbCrAndRgbConverter YCbCrAndRgbConverter = new YCbCrAndRgbConverter();
/// <summary>
/// Performs the bulk conversion from <see cref="CieLab"/> into <see cref="YCbCr"/>.
/// </summary>
@ -124,7 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Cmyk> source, Span<YCbCr> destination)
public static void Convert(ReadOnlySpan<Cmyk> source, Span<YCbCr> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -136,7 +134,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Cmyk sp = ref Unsafe.Add(ref sourceRef, i);
ref YCbCr dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToYCbCr(sp);
dp = ToYCbCr(sp);
}
}
@ -145,7 +143,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Hsl> source, Span<YCbCr> destination)
public static void Convert(ReadOnlySpan<Hsl> source, Span<YCbCr> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -157,7 +155,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsl sp = ref Unsafe.Add(ref sourceRef, i);
ref YCbCr dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToYCbCr(sp);
dp = ToYCbCr(sp);
}
}
@ -166,7 +164,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Hsv> source, Span<YCbCr> destination)
public static void Convert(ReadOnlySpan<Hsv> source, Span<YCbCr> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -178,7 +176,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Hsv sp = ref Unsafe.Add(ref sourceRef, i);
ref YCbCr dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToYCbCr(sp);
dp = ToYCbCr(sp);
}
}
@ -208,7 +206,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<LinearRgb> source, Span<YCbCr> destination)
public static void Convert(ReadOnlySpan<LinearRgb> source, Span<YCbCr> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -220,7 +218,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref LinearRgb sp = ref Unsafe.Add(ref sourceRef, i);
ref YCbCr dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToYCbCr(sp);
dp = ToYCbCr(sp);
}
}
@ -250,7 +248,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="source">The span to the source colors</param>
/// <param name="destination">The span to the destination colors</param>
public void Convert(ReadOnlySpan<Rgb> source, Span<YCbCr> destination)
public static void Convert(ReadOnlySpan<Rgb> source, Span<YCbCr> destination)
{
Guard.DestinationShouldNotBeTooShort(source, destination, nameof(destination));
int count = source.Length;
@ -262,7 +260,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
ref Rgb sp = ref Unsafe.Add(ref sourceRef, i);
ref YCbCr dp = ref Unsafe.Add(ref destRef, i);
dp = this.ToYCbCr(sp);
dp = ToYCbCr(sp);
}
}
@ -273,7 +271,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in CieLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
}
@ -285,7 +283,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in CieLch color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
}
@ -297,7 +295,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in CieLuv color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
}
@ -309,7 +307,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in CieXyy color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = ToCieXyz(color);
return this.ToYCbCr(xyzColor);
}
@ -321,7 +319,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in CieXyz color)
{
var rgb = this.ToRgb(color);
Rgb rgb = this.ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
}
@ -331,9 +329,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in Cmyk color)
public static YCbCr ToYCbCr(in Cmyk color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
}
@ -343,9 +341,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in Hsl color)
public static YCbCr ToYCbCr(in Hsl color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
}
@ -355,9 +353,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in Hsv color)
public static YCbCr ToYCbCr(in Hsv color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
}
@ -369,7 +367,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in HunterLab color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
}
@ -379,9 +377,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in LinearRgb color)
public static YCbCr ToYCbCr(in LinearRgb color)
{
var rgb = this.ToRgb(color);
Rgb rgb = ToRgb(color);
return YCbCrAndRgbConverter.Convert(rgb);
}
@ -393,7 +391,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in Lms color)
{
var xyzColor = this.ToCieXyz(color);
CieXyz xyzColor = this.ToCieXyz(color);
return this.ToYCbCr(xyzColor);
}
@ -403,6 +401,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
/// <param name="color">The color to convert.</param>
/// <returns>The <see cref="YCbCr"/></returns>
public YCbCr ToYCbCr(in Rgb color) => YCbCrAndRgbConverter.Convert(color);
public static YCbCr ToYCbCr(in Rgb color) => YCbCrAndRgbConverter.Convert(color);
}
}

46
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs

@ -12,13 +12,25 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// </summary>
public readonly struct CieXyChromaticityCoordinates : IEquatable<CieXyChromaticityCoordinates>
{
/// <summary>
/// Initializes a new instance of the <see cref="CieXyChromaticityCoordinates"/> struct.
/// </summary>
/// <param name="x">Chromaticity coordinate x (usually from 0 to 1)</param>
/// <param name="y">Chromaticity coordinate y (usually from 0 to 1)</param>
[MethodImpl(InliningOptions.ShortMethod)]
public CieXyChromaticityCoordinates(float x, float y)
{
this.X = x;
this.Y = y;
}
/// <summary>
/// Gets the chromaticity X-coordinate.
/// </summary>
/// <remarks>
/// Ranges usually from 0 to 1.
/// </remarks>
public readonly float X;
public readonly float X { get; }
/// <summary>
/// Gets the chromaticity Y-coordinate
@ -26,19 +38,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <remarks>
/// Ranges usually from 0 to 1.
/// </remarks>
public readonly float Y;
/// <summary>
/// Initializes a new instance of the <see cref="CieXyChromaticityCoordinates"/> struct.
/// </summary>
/// <param name="x">Chromaticity coordinate x (usually from 0 to 1)</param>
/// <param name="y">Chromaticity coordinate y (usually from 0 to 1)</param>
[MethodImpl(InliningOptions.ShortMethod)]
public CieXyChromaticityCoordinates(float x, float y)
{
this.X = x;
this.Y = y;
}
public readonly float Y { get; }
/// <summary>
/// Compares two <see cref="CieXyChromaticityCoordinates"/> objects for equality.
@ -49,7 +49,8 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) => left.Equals(right);
public static bool operator ==(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right)
=> left.Equals(right);
/// <summary>
/// Compares two <see cref="CieXyChromaticityCoordinates"/> objects for inequality
@ -60,20 +61,25 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right) => !left.Equals(right);
public static bool operator !=(CieXyChromaticityCoordinates left, CieXyChromaticityCoordinates right)
=> !left.Equals(right);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => HashCode.Combine(this.X, this.Y);
public override int GetHashCode()
=> HashCode.Combine(this.X, this.Y);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieXyChromaticityCoordinates({this.X:#0.##}, {this.Y:#0.##})");
public override string ToString()
=> FormattableString.Invariant($"CieXyChromaticityCoordinates({this.X:#0.##}, {this.Y:#0.##})");
/// <inheritdoc/>
public override bool Equals(object obj) => obj is CieXyChromaticityCoordinates other && this.Equals(other);
public override bool Equals(object obj)
=> obj is CieXyChromaticityCoordinates other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(CieXyChromaticityCoordinates other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
public bool Equals(CieXyChromaticityCoordinates other)
=> this.X.Equals(other.X) && this.Y.Equals(other.Y);
}
}

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CIeLchToCieLabConverter.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.
/// </summary>
internal sealed class CieLchToCieLabConverter
internal static class CieLchToCieLabConverter
{
/// <summary>
/// Performs the conversion from the <see cref="CieLch"/> input to an instance of <see cref="CieLab"/> type.
@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieLab Convert(in CieLch input)
public static CieLab Convert(in CieLch input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieLchConverter.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
/// </summary>
internal sealed class CieLabToCieLchConverter
internal static class CieLabToCieLchConverter
{
/// <summary>
/// Performs the conversion from the <see cref="CieLab"/> input to an instance of <see cref="CieLch"/> type.
@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieLch Convert(in CieLab input)
public static CieLch Convert(in CieLab input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/Lab_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC

8
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Converts from <see cref="CieLab"/> to <see cref="CieXyz"/>.
/// </summary>
internal sealed class CieLabToCieXyzConverter
internal static class CieLabToCieXyzConverter
{
/// <summary>
/// Performs the conversion from the <see cref="CieLab"/> input to an instance of <see cref="CieXyz"/> type.
@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieXyz Convert(in CieLab input)
public static CieXyz Convert(in CieLab input)
{
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Lab_to_XYZ.html
float l = input.L, a = input.A, b = input.B;
@ -32,10 +32,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? Numerics.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa;
float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa;
var wxyz = new Vector3(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z);
Vector3 wxyz = new(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z);
// Avoids XYZ coordinates out range (restricted by 0 and XYZ reference white)
var xyzr = Vector3.Clamp(new Vector3(xr, yr, zr), Vector3.Zero, Vector3.One);
Vector3 xyzr = Vector3.Clamp(new Vector3(xr, yr, zr), Vector3.Zero, Vector3.One);
Vector3 xyz = xyzr * wxyz;
return new CieXyz(xyz);

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLchuvToCieLuvConverter.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Converts from <see cref="CieLch"/> to <see cref="CieLab"/>.
/// </summary>
internal sealed class CieLchuvToCieLuvConverter
internal static class CieLchuvToCieLuvConverter
{
/// <summary>
/// Performs the conversion from the <see cref="CieLchuv"/> input to an instance of <see cref="CieLuv"/> type.
@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieLuv Convert(in CieLchuv input)
public static CieLuv Convert(in CieLchuv input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieLchuvConverter.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Converts from <see cref="CieLab"/> to <see cref="CieLch"/>.
/// </summary>
internal sealed class CieLuvToCieLchuvConverter
internal static class CieLuvToCieLchuvConverter
{
/// <summary>
/// Performs the conversion from the <see cref="CieLuv"/> input to an instance of <see cref="CieLchuv"/> type.
@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieLchuv Convert(in CieLuv input)
public static CieLchuv Convert(in CieLuv input)
{
// Conversion algorithm described here:
// https://en.wikipedia.org/wiki/CIELUV#Cylindrical_representation_.28CIELCH.29

4
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs

@ -8,14 +8,14 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Converts from <see cref="CieLuv"/> to <see cref="CieXyz"/>.
/// </summary>
internal sealed class CieLuvToCieXyzConverter
internal static class CieLuvToCieXyzConverter
{
/// <summary>
/// Performs the conversion from the <see cref="CieLuv"/> input to an instance of <see cref="CieXyz"/> type.
/// </summary>
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
public CieXyz Convert(in CieLuv input)
public static CieXyz Convert(in CieLuv input)
{
// Conversion algorithm described here: http://www.brucelindbloom.com/index.html?Eqn_Luv_to_XYZ.html
float l = input.L, u = input.U, v = input.V;

8
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndCieXyyConverter.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// Color converter between CIE XYZ and CIE xyY.
/// <see href="http://www.brucelindbloom.com/"/> for formulas.
/// </summary>
internal sealed class CieXyzAndCieXyyConverter
internal static class CieXyzAndCieXyyConverter
{
/// <summary>
/// Performs the conversion from the <see cref="CieXyz"/> input to an instance of <see cref="CieXyy"/> type.
@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieXyy Convert(in CieXyz input)
public static CieXyy Convert(in CieXyz input)
{
float x = input.X / (input.X + input.Y + input.Z);
float y = input.Y / (input.X + input.Y + input.Z);
@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieXyz Convert(in CieXyy input)
public static CieXyz Convert(in CieXyy input)
{
if (MathF.Abs(input.Y) < Constants.Epsilon)
{

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieXyzAndLmsConverter.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Numerics;
@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
[MethodImpl(InliningOptions.ShortMethod)]
public Lms Convert(in CieXyz input)
{
var vector = Vector3.Transform(input.ToVector3(), this.transformationMatrix);
Vector3 vector = Vector3.Transform(input.ToVector3(), this.transformationMatrix);
return new Lms(vector);
}
@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
[MethodImpl(InliningOptions.ShortMethod)]
public CieXyz Convert(in Lms input)
{
var vector = Vector3.Transform(input.ToVector3(), this.inverseTransformationMatrix);
Vector3 vector = Vector3.Transform(input.ToVector3(), this.inverseTransformationMatrix);
return new CieXyz(vector);
}

10
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CmykAndRgbConverter.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Color converter between <see cref="Cmyk"/> and <see cref="Rgb"/>.
/// </summary>
internal sealed class CmykAndRgbConverter
internal static class CmykAndRgbConverter
{
/// <summary>
/// Performs the conversion from the <see cref="Cmyk"/> input to an instance of <see cref="Rgb"/> type.
@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb Convert(in Cmyk input)
public static Rgb Convert(in Cmyk input)
{
Vector3 rgb = (Vector3.One - new Vector3(input.C, input.M, input.Y)) * (Vector3.One - new Vector3(input.K));
return new Rgb(rgb);
@ -30,13 +30,13 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Cmyk Convert(in Rgb input)
public static Cmyk Convert(in Rgb input)
{
// To CMY
Vector3 cmy = Vector3.One - input.ToVector3();
// To CMYK
var k = new Vector3(MathF.Min(cmy.X, MathF.Min(cmy.Y, cmy.Z)));
Vector3 k = new(MathF.Min(cmy.X, MathF.Min(cmy.Y, cmy.Z)));
if (MathF.Abs(k.X - 1F) < Constants.Epsilon)
{

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HslAndRgbConverter.cs

@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// Color converter between HSL and Rgb
/// See <see href="http://www.poynton.com/PDFs/coloureq.pdf"/> for formulas.
/// </summary>
internal sealed class HslAndRgbConverter
internal static class HslAndRgbConverter
{
/// <summary>
/// Performs the conversion from the <see cref="Hsl"/> input to an instance of <see cref="Rgb"/> type.
@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb Convert(in Hsl input)
public static Rgb Convert(in Hsl input)
{
float rangedH = input.H / 360F;
float r = 0;
@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Hsl Convert(in Rgb input)
public static Hsl Convert(in Rgb input)
{
float r = input.R;
float g = input.G;

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HsvAndRgbConverter.cs

@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// Color converter between HSV and Rgb
/// See <see href="http://www.poynton.com/PDFs/coloureq.pdf"/> for formulas.
/// </summary>
internal sealed class HsvAndRgbConverter
internal static class HsvAndRgbConverter
{
/// <summary>
/// Performs the conversion from the <see cref="Hsv"/> input to an instance of <see cref="Rgb"/> type.
@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb Convert(in Hsv input)
public static Rgb Convert(in Hsv input)
{
float s = input.S;
float v = input.V;
@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Hsv Convert(in Rgb input)
public static Hsv Convert(in Rgb input)
{
float r = input.R;
float g = input.G;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs

@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public CieXyz Convert(in HunterLab input)
public static CieXyz Convert(in HunterLab input)
{
// Conversion algorithm described here: http://en.wikipedia.org/wiki/Lab_color_space#Hunter_Lab
float l = input.L, a = input.A, b = input.B;

19
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbAndCieXyzConverterBase.cs

@ -28,25 +28,22 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
float yb = chromaticity.B.Y;
float mXr = xr / yr;
const float Yr = 1;
float mZr = (1 - xr - yr) / yr;
float mXg = xg / yg;
const float Yg = 1;
float mZg = (1 - xg - yg) / yg;
float mXb = xb / yb;
const float Yb = 1;
float mZb = (1 - xb - yb) / yb;
var xyzMatrix = new Matrix4x4
Matrix4x4 xyzMatrix = new()
{
M11 = mXr,
M21 = mXg,
M31 = mXb,
M12 = Yr,
M22 = Yg,
M32 = Yb,
M12 = 1F,
M22 = 1F,
M32 = 1F,
M13 = mZr,
M23 = mZg,
M33 = mZb,
@ -55,7 +52,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
Matrix4x4.Invert(xyzMatrix, out Matrix4x4 inverseXyzMatrix);
var vector = Vector3.Transform(workingSpace.WhitePoint.ToVector3(), inverseXyzMatrix);
Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.ToVector3(), inverseXyzMatrix);
// Use transposed Rows/Columns
// TODO: Is there a built in method for this multiplication?
@ -64,9 +61,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
M11 = vector.X * mXr,
M21 = vector.Y * mXg,
M31 = vector.Z * mXb,
M12 = vector.X * Yr,
M22 = vector.Y * Yg,
M32 = vector.Z * Yb,
M12 = vector.X * 1,
M22 = vector.Y * 1,
M32 = vector.Z * 1,
M13 = vector.X * mZr,
M23 = vector.Y * mZg,
M33 = vector.Z * mZb,

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToCieXyzConverter.cs

@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
{
DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal.");
var vector = Vector3.Transform(input.ToVector3(), this.conversionMatrix);
Vector3 vector = Vector3.Transform(input.ToVector3(), this.conversionMatrix);
return new CieXyz(vector);
}
}

8
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/LinearRgbToRgbConverter.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Color converter between <see cref="LinearRgb"/> and <see cref="Rgb"/>.
/// </summary>
internal sealed class LinearRgbToRgbConverter
internal static class LinearRgbToRgbConverter
{
/// <summary>
/// Performs the conversion from the <see cref="LinearRgb"/> input to an instance of <see cref="Rgb"/> type.
@ -16,13 +16,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb Convert(in LinearRgb input)
{
return new Rgb(
public static Rgb Convert(in LinearRgb input) =>
new(
r: input.WorkingSpace.Compress(input.R),
g: input.WorkingSpace.Compress(input.G),
b: input.WorkingSpace.Compress(input.B),
workingSpace: input.WorkingSpace);
}
}
}

8
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/RgbToLinearRgbConverter.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <summary>
/// Color converter between Rgb and LinearRgb.
/// </summary>
internal class RgbToLinearRgbConverter
internal static class RgbToLinearRgbConverter
{
/// <summary>
/// Performs the conversion from the <see cref="Rgb"/> input to an instance of <see cref="LinearRgb"/> type.
@ -16,13 +16,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public LinearRgb Convert(in Rgb input)
{
return new LinearRgb(
public static LinearRgb Convert(in Rgb input)
=> new(
r: input.WorkingSpace.Expand(input.R),
g: input.WorkingSpace.Expand(input.G),
b: input.WorkingSpace.Expand(input.B),
workingSpace: input.WorkingSpace);
}
}
}

8
src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/YCbCrAndRgbConverter.cs

@ -11,9 +11,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// Color converter between <see cref="YCbCr"/> and <see cref="Rgb"/>
/// See <see href="https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion"/> for formulas.
/// </summary>
internal sealed class YCbCrAndRgbConverter
internal static class YCbCrAndRgbConverter
{
private static readonly Vector3 MaxBytes = new Vector3(255F);
private static readonly Vector3 MaxBytes = new(255F);
/// <summary>
/// Performs the conversion from the <see cref="YCbCr"/> input to an instance of <see cref="Rgb"/> type.
@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb Convert(in YCbCr input)
public static Rgb Convert(in YCbCr input)
{
float y = input.Y;
float cb = input.Cb - 128F;
@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
/// <param name="input">The input color instance.</param>
/// <returns>The converted result.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public YCbCr Convert(in Rgb input)
public static YCbCr Convert(in Rgb input)
{
Vector3 rgb = input.ToVector3() * MaxBytes;
float r = rgb.X;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/VonKriesChromaticAdaptation.cs

@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
if (sourceWhitePoint.Equals(destinationWhitePoint))
{
source.CopyTo(destination.Slice(0, count));
source.CopyTo(destination[..count]);
return;
}

48
src/ImageSharp/ColorSpaces/Hsl.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -13,25 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public readonly struct Hsl : IEquatable<Hsl>
{
private static readonly Vector3 Min = Vector3.Zero;
private static readonly Vector3 Max = new Vector3(360, 1, 1);
/// <summary>
/// Gets the hue component.
/// <remarks>A value ranging between 0 and 360.</remarks>
/// </summary>
public readonly float H;
/// <summary>
/// Gets the saturation component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float S;
/// <summary>
/// Gets the lightness component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float L;
private static readonly Vector3 Max = new(360, 1, 1);
/// <summary>
/// Initializes a new instance of the <see cref="Hsl"/> struct.
@ -58,6 +40,24 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.L = vector.Z;
}
/// <summary>
/// Gets the hue component.
/// <remarks>A value ranging between 0 and 360.</remarks>
/// </summary>
public readonly float H { get; }
/// <summary>
/// Gets the saturation component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float S { get; }
/// <summary>
/// Gets the lightness component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float L { get; }
/// <summary>
/// Compares two <see cref="Hsl"/> objects for equality.
/// </summary>
@ -95,10 +95,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Hsl other)
{
return this.H.Equals(other.H)
&& this.S.Equals(other.S)
&& this.L.Equals(other.L);
}
=> this.H.Equals(other.H)
&& this.S.Equals(other.S)
&& this.L.Equals(other.L);
}
}

48
src/ImageSharp/ColorSpaces/Hsv.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -13,25 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public readonly struct Hsv : IEquatable<Hsv>
{
private static readonly Vector3 Min = Vector3.Zero;
private static readonly Vector3 Max = new Vector3(360, 1, 1);
/// <summary>
/// Gets the hue component.
/// <remarks>A value ranging between 0 and 360.</remarks>
/// </summary>
public readonly float H;
/// <summary>
/// Gets the saturation component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float S;
/// <summary>
/// Gets the value (brightness) component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float V;
private static readonly Vector3 Max = new(360, 1, 1);
/// <summary>
/// Initializes a new instance of the <see cref="Hsv"/> struct.
@ -58,6 +40,24 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.V = vector.Z;
}
/// <summary>
/// Gets the hue component.
/// <remarks>A value ranging between 0 and 360.</remarks>
/// </summary>
public readonly float H { get; }
/// <summary>
/// Gets the saturation component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float S { get; }
/// <summary>
/// Gets the value (brightness) component.
/// <remarks>A value ranging between 0 and 1.</remarks>
/// </summary>
public readonly float V { get; }
/// <summary>
/// Compares two <see cref="Hsv"/> objects for equality.
/// </summary>
@ -93,10 +93,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Hsv other)
{
return this.H.Equals(other.H)
&& this.S.Equals(other.S)
&& this.V.Equals(other.V);
}
=> this.H.Equals(other.H)
&& this.S.Equals(other.S)
&& this.V.Equals(other.V);
}
}

58
src/ImageSharp/ColorSpaces/HunterLab.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -19,29 +19,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public static readonly CieXyz DefaultWhitePoint = Illuminants.C;
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L;
/// <summary>
/// Gets the a color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
/// </summary>
public readonly float A;
/// <summary>
/// Gets the b color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
/// </summary>
public readonly float B;
/// <summary>
/// Gets the reference white point of this color.
/// </summary>
public readonly CieXyz WhitePoint;
/// <summary>
/// Initializes a new instance of the <see cref="HunterLab"/> struct.
/// </summary>
@ -94,6 +71,29 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.WhitePoint = whitePoint;
}
/// <summary>
/// Gets the lightness dimension.
/// <remarks>A value usually ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
/// </summary>
public readonly float L { get; }
/// <summary>
/// Gets the a color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is green, positive magenta.</remarks>
/// </summary>
public readonly float A { get; }
/// <summary>
/// Gets the b color component.
/// <remarks>A value usually ranging from -100 to 100. Negative is blue, positive is yellow</remarks>
/// </summary>
public readonly float B { get; }
/// <summary>
/// Gets the reference white point of this color.
/// </summary>
public readonly CieXyz WhitePoint { get; }
/// <summary>
/// Compares two <see cref="HunterLab"/> objects for equality.
/// </summary>
@ -128,11 +128,9 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(HunterLab other)
{
return this.L.Equals(other.L)
&& this.A.Equals(other.A)
&& this.B.Equals(other.B)
&& this.WhitePoint.Equals(other.WhitePoint);
}
=> this.L.Equals(other.L)
&& this.A.Equals(other.A)
&& this.B.Equals(other.B)
&& this.WhitePoint.Equals(other.WhitePoint);
}
}

56
src/ImageSharp/ColorSpaces/LinearRgb.cs

@ -21,29 +21,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public static readonly RgbWorkingSpace DefaultWorkingSpace = RgbWorkingSpaces.SRgb;
/// <summary>
/// Gets the red component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float R;
/// <summary>
/// Gets the green component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float G;
/// <summary>
/// Gets the blue component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float B;
/// <summary>
/// Gets the LinearRgb color space <seealso cref="RgbWorkingSpaces"/>
/// </summary>
public readonly RgbWorkingSpace WorkingSpace;
/// <summary>
/// Initializes a new instance of the <see cref="LinearRgb"/> struct.
/// </summary>
@ -95,6 +72,29 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.WorkingSpace = workingSpace;
}
/// <summary>
/// Gets the red component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float R { get; }
/// <summary>
/// Gets the green component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float G { get; }
/// <summary>
/// Gets the blue component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float B { get; }
/// <summary>
/// Gets the LinearRgb color space <seealso cref="RgbWorkingSpaces"/>
/// </summary>
public readonly RgbWorkingSpace WorkingSpace { get; }
/// <summary>
/// Compares two <see cref="LinearRgb"/> objects for equality.
/// </summary>
@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
/// <returns>The <see cref="Vector3"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector3 ToVector3() => new Vector3(this.R, this.G, this.B);
public Vector3 ToVector3() => new(this.R, this.G, this.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
@ -137,10 +137,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(LinearRgb other)
{
return this.R.Equals(other.R)
&& this.G.Equals(other.G)
&& this.B.Equals(other.B);
}
=> this.R.Equals(other.R)
&& this.G.Equals(other.G)
&& this.B.Equals(other.B);
}
}

48
src/ImageSharp/ColorSpaces/Lms.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
@ -14,24 +14,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
public readonly struct Lms : IEquatable<Lms>
{
/// <summary>
/// Gets the L long component.
/// <remarks>A value usually ranging between -1 and 1.</remarks>
/// </summary>
public readonly float L;
/// <summary>
/// Gets the M medium component.
/// <remarks>A value usually ranging between -1 and 1.</remarks>
/// </summary>
public readonly float M;
/// <summary>
/// Gets the S short component.
/// <remarks>A value usually ranging between -1 and 1.</remarks>
/// </summary>
public readonly float S;
/// <summary>
/// Initializes a new instance of the <see cref="Lms"/> struct.
/// </summary>
@ -57,6 +39,24 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.S = vector.Z;
}
/// <summary>
/// Gets the L long component.
/// <remarks>A value usually ranging between -1 and 1.</remarks>
/// </summary>
public readonly float L { get; }
/// <summary>
/// Gets the M medium component.
/// <remarks>A value usually ranging between -1 and 1.</remarks>
/// </summary>
public readonly float M { get; }
/// <summary>
/// Gets the S short component.
/// <remarks>A value usually ranging between -1 and 1.</remarks>
/// </summary>
public readonly float S { get; }
/// <summary>
/// Compares two <see cref="Lms"/> objects for equality.
/// </summary>
@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
/// <returns>The <see cref="Vector3"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector3 ToVector3() => new Vector3(this.L, this.M, this.S);
public Vector3 ToVector3() => new(this.L, this.M, this.S);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.L, this.M, this.S);
@ -98,10 +98,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Lms other)
{
return this.L.Equals(other.L)
&& this.M.Equals(other.M)
&& this.S.Equals(other.S);
}
=> this.L.Equals(other.L)
&& this.M.Equals(other.M)
&& this.S.Equals(other.S);
}
}

60
src/ImageSharp/ColorSpaces/Rgb.cs

@ -22,29 +22,6 @@ namespace SixLabors.ImageSharp.ColorSpaces
private static readonly Vector3 Min = Vector3.Zero;
private static readonly Vector3 Max = Vector3.One;
/// <summary>
/// Gets the red component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float R;
/// <summary>
/// Gets the green component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float G;
/// <summary>
/// Gets the blue component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float B;
/// <summary>
/// Gets the Rgb color space <seealso cref="RgbWorkingSpaces"/>
/// </summary>
public readonly RgbWorkingSpace WorkingSpace;
/// <summary>
/// Initializes a new instance of the <see cref="Rgb"/> struct.
/// </summary>
@ -95,6 +72,29 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.WorkingSpace = workingSpace;
}
/// <summary>
/// Gets the red component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float R { get; }
/// <summary>
/// Gets the green component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float G { get; }
/// <summary>
/// Gets the blue component.
/// <remarks>A value usually ranging between 0 and 1.</remarks>
/// </summary>
public readonly float B { get; }
/// <summary>
/// Gets the Rgb color space <seealso cref="RgbWorkingSpaces"/>
/// </summary>
public readonly RgbWorkingSpace WorkingSpace { get; }
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Rgb24"/> to a
/// <see cref="Rgb"/>.
@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <param name="color">The instance of <see cref="Rgba32"/> to convert.</param>
/// <returns>An instance of <see cref="Rgb"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static implicit operator Rgb(Rgb24 color) => new Rgb(color.R / 255F, color.G / 255F, color.B / 255F);
public static implicit operator Rgb(Rgb24 color) => new(color.R / 255F, color.G / 255F, color.B / 255F);
/// <summary>
/// Allows the implicit conversion of an instance of <see cref="Rgba32"/> to a
@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <param name="color">The instance of <see cref="Rgba32"/> to convert.</param>
/// <returns>An instance of <see cref="Rgb"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static implicit operator Rgb(Rgba32 color) => new Rgb(color.R / 255F, color.G / 255F, color.B / 255F);
public static implicit operator Rgb(Rgba32 color) => new(color.R / 255F, color.G / 255F, color.B / 255F);
/// <summary>
/// Compares two <see cref="Rgb"/> objects for equality.
@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// </summary>
/// <returns>The <see cref="Vector3"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector3 ToVector3() => new Vector3(this.R, this.G, this.B);
public Vector3 ToVector3() => new(this.R, this.G, this.B);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B);
@ -158,10 +158,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Rgb other)
{
return this.R.Equals(other.R)
&& this.G.Equals(other.G)
&& this.B.Equals(other.B);
}
=> this.R.Equals(other.R)
&& this.G.Equals(other.G)
&& this.B.Equals(other.B);
}
}

46
src/ImageSharp/ColorSpaces/YCbCr.cs

@ -15,25 +15,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public readonly struct YCbCr : IEquatable<YCbCr>
{
private static readonly Vector3 Min = Vector3.Zero;
private static readonly Vector3 Max = new Vector3(255);
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public readonly float Y;
/// <summary>
/// Gets the Cb chroma component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public readonly float Cb;
/// <summary>
/// Gets the Cr chroma component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public readonly float Cr;
private static readonly Vector3 Max = new(255);
/// <summary>
/// Initializes a new instance of the <see cref="YCbCr"/> struct.
@ -60,6 +42,24 @@ namespace SixLabors.ImageSharp.ColorSpaces
this.Cr = vector.Z;
}
/// <summary>
/// Gets the Y luminance component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public readonly float Y { get; }
/// <summary>
/// Gets the Cb chroma component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public readonly float Cb { get; }
/// <summary>
/// Gets the Cr chroma component.
/// <remarks>A value ranging between 0 and 255.</remarks>
/// </summary>
public readonly float Cr { get; }
/// <summary>
/// Compares two <see cref="YCbCr"/> objects for equality.
/// </summary>
@ -94,10 +94,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(YCbCr other)
{
return this.Y.Equals(other.Y)
&& this.Cb.Equals(other.Cb)
&& this.Cr.Equals(other.Cr);
}
=> this.Y.Equals(other.Y)
&& this.Cb.Equals(other.Cb)
&& this.Cr.Equals(other.Cr);
}
}

35
src/ImageSharp/Common/Extensions/EncoderExtensions.cs

@ -1,35 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if !SUPPORTS_ENCODING_STRING
using System;
using System.Text;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Extension methods for the <see cref="Encoder"/> type.
/// </summary>
internal static unsafe class EncoderExtensions
{
/// <summary>
/// Gets a string from the provided buffer data.
/// </summary>
/// <param name="encoding">The encoding.</param>
/// <param name="buffer">The buffer.</param>
/// <returns>The string.</returns>
public static string GetString(this Encoding encoding, ReadOnlySpan<byte> buffer)
{
if (buffer.Length == 0)
{
return string.Empty;
}
fixed (byte* bytes = buffer)
{
return encoding.GetString(bytes, buffer.Length);
}
}
}
}
#endif

46
src/ImageSharp/Common/Extensions/StreamExtensions.cs

@ -70,51 +70,5 @@ namespace SixLabors.ImageSharp
ArrayPool<byte>.Shared.Return(buffer);
}
}
#if !SUPPORTS_SPAN_STREAM
// This is a port of the CoreFX implementation and is MIT Licensed:
// https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L742
public static int Read(this Stream stream, Span<byte> buffer)
{
// This uses ArrayPool<byte>.Shared, rather than taking a MemoryAllocator,
// in order to match the signature of the framework method that exists in
// .NET Core.
byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
try
{
int numRead = stream.Read(sharedBuffer, 0, buffer.Length);
if ((uint)numRead > (uint)buffer.Length)
{
throw new IOException("Stream was too long.");
}
new Span<byte>(sharedBuffer, 0, numRead).CopyTo(buffer);
return numRead;
}
finally
{
ArrayPool<byte>.Shared.Return(sharedBuffer);
}
}
// This is a port of the CoreFX implementation and is MIT Licensed:
// https://github.com/dotnet/corefx/blob/17300169760c61a90cab8d913636c1058a30a8c1/src/Common/src/CoreLib/System/IO/Stream.cs#L775
public static void Write(this Stream stream, ReadOnlySpan<byte> buffer)
{
// This uses ArrayPool<byte>.Shared, rather than taking a MemoryAllocator,
// in order to match the signature of the framework method that exists in
// .NET Core.
byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
try
{
buffer.CopyTo(sharedBuffer);
stream.Write(sharedBuffer, 0, buffer.Length);
}
finally
{
ArrayPool<byte>.Shared.Return(sharedBuffer);
}
}
#endif
}
}

2
src/ImageSharp/Common/Helpers/HexConverter.cs

@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Common.Helpers
{
// Slightly better performance in the loop below, allows us to skip a bounds check
// while still supporting output buffers that are larger than necessary
bytes = bytes.Slice(0, chars.Length / 2);
bytes = bytes[..(chars.Length / 2)];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

6
src/ImageSharp/Common/Helpers/InliningOptions.cs

@ -18,13 +18,11 @@ namespace SixLabors.ImageSharp
public const MethodImplOptions AlwaysInline = MethodImplOptions.AggressiveInlining;
#if PROFILING
public const MethodImplOptions HotPath = MethodImplOptions.NoInlining;
public const MethodImplOptions ShortMethod = MethodImplOptions.NoInlining;
#else
#if SUPPORTS_HOTPATH
public const MethodImplOptions HotPath = MethodImplOptions.AggressiveOptimization;
#else
public const MethodImplOptions HotPath = MethodImplOptions.AggressiveInlining;
#endif
public const MethodImplOptions ShortMethod = MethodImplOptions.AggressiveInlining;
#endif
public const MethodImplOptions ColdPath = MethodImplOptions.NoInlining;

146
src/ImageSharp/Common/Helpers/Numerics.cs

@ -5,10 +5,8 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
namespace SixLabors.ImageSharp
{
@ -18,20 +16,8 @@ namespace SixLabors.ImageSharp
/// </summary>
internal static class Numerics
{
#if SUPPORTS_RUNTIME_INTRINSICS
public const int BlendAlphaControl = 0b_10_00_10_00;
private const int ShuffleAlphaControl = 0b_11_11_11_11;
#endif
#if !SUPPORTS_BITOPERATIONS
private static ReadOnlySpan<byte> Log2DeBruijn => new byte[32]
{
00, 09, 01, 10, 13, 21, 02, 29,
11, 14, 16, 18, 22, 25, 03, 30,
08, 12, 20, 28, 15, 17, 24, 07,
19, 27, 23, 06, 26, 05, 04, 31
};
#endif
/// <summary>
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
@ -129,13 +115,13 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Gaussian(float x, float sigma)
{
const float Numerator = 1.0f;
const float numerator = 1.0f;
float denominator = MathF.Sqrt(2 * MathF.PI) * sigma;
float exponentNumerator = -x * x;
float exponentDenominator = 2 * Pow2(sigma);
float left = Numerator / denominator;
float left = numerator / denominator;
float right = MathF.Exp(exponentNumerator / exponentDenominator);
return left * right;
@ -300,7 +286,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<byte> span, byte min, byte max)
{
Span<byte> remainder = span.Slice(ClampReduce(span, min, max));
Span<byte> remainder = span[ClampReduce(span, min, max)..];
if (remainder.Length > 0)
{
@ -325,7 +311,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<uint> span, uint min, uint max)
{
Span<uint> remainder = span.Slice(ClampReduce(span, min, max));
Span<uint> remainder = span[ClampReduce(span, min, max)..];
if (remainder.Length > 0)
{
@ -350,7 +336,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<int> span, int min, int max)
{
Span<int> remainder = span.Slice(ClampReduce(span, min, max));
Span<int> remainder = span[ClampReduce(span, min, max)..];
if (remainder.Length > 0)
{
@ -375,7 +361,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<float> span, float min, float max)
{
Span<float> remainder = span.Slice(ClampReduce(span, min, max));
Span<float> remainder = span[ClampReduce(span, min, max)..];
if (remainder.Length > 0)
{
@ -400,7 +386,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<double> span, double min, double max)
{
Span<double> remainder = span.Slice(ClampReduce(span, min, max));
Span<double> remainder = span[ClampReduce(span, min, max)..];
if (remainder.Length > 0)
{
@ -427,7 +413,7 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
ClampImpl(span.Slice(0, adjustedCount), min, max);
ClampImpl(span[..adjustedCount], min, max);
}
return adjustedCount;
@ -512,7 +498,6 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Premultiply(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
@ -530,11 +515,10 @@ namespace SixLabors.ImageSharp
if (Modulo2(vectors.Length) != 0)
{
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
Premultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
Premultiply(ref MemoryMarshal.GetReference(vectors[^1..]));
}
}
else
#endif
{
ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length);
@ -555,7 +539,6 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UnPremultiply(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
@ -573,11 +556,10 @@ namespace SixLabors.ImageSharp
if (Modulo2(vectors.Length) != 0)
{
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
UnPremultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
UnPremultiply(ref MemoryMarshal.GetReference(vectors[^1..]));
}
}
else
#endif
{
ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length);
@ -627,7 +609,6 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void CubeRootOnXYZ(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Sse41.IsSupported)
{
ref Vector128<float> vectors128Ref = ref Unsafe.As<Vector4, Vector128<float>>(ref MemoryMarshal.GetReference(vectors));
@ -678,7 +659,6 @@ namespace SixLabors.ImageSharp
}
}
else
#endif
{
ref Vector4 vectorsRef = ref MemoryMarshal.GetReference(vectors);
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsRef, vectors.Length);
@ -727,8 +707,6 @@ namespace SixLabors.ImageSharp
}
}
#if SUPPORTS_RUNTIME_INTRINSICS
/// <summary>
/// Performs a linear interpolation between two values based on the given weighting.
/// </summary>
@ -752,7 +730,6 @@ namespace SixLabors.ImageSharp
return Avx.Add(Avx.Multiply(diff, amount), value1);
}
}
#endif
/// <summary>
/// Performs a linear interpolation between two values based on the given weighting.
@ -765,8 +742,6 @@ namespace SixLabors.ImageSharp
public static float Lerp(float value1, float value2, float amount)
=> ((value2 - value1) * amount) + value1;
#if SUPPORTS_RUNTIME_INTRINSICS
/// <summary>
/// Accumulates 8-bit integers into <paramref name="accumulator"/> by
/// widening them to 32-bit integers and performing four additions.
@ -860,51 +835,6 @@ namespace SixLabors.ImageSharp
// Vector128<int>.ToScalar() isn't optimized pre-net5.0 https://github.com/dotnet/runtime/pull/37882
return Sse2.ConvertToInt32(vsum);
}
#endif
/// <summary>
/// Calculates floored log of the specified value, base 2.
/// Note that by convention, input value 0 returns 0 since Log(0) is undefined.
/// </summary>
/// <param name="value">The value.</param>
public static int Log2(uint value)
{
#if SUPPORTS_BITOPERATIONS
return BitOperations.Log2(value);
#else
return Log2SoftwareFallback(value);
#endif
}
#if !SUPPORTS_BITOPERATIONS
/// <summary>
/// Calculates floored log of the specified value, base 2.
/// Note that by convention, input value 0 returns 0 since Log(0) is undefined.
/// Bit hacking with deBruijn sequence, extremely fast yet does not use any intrinsics so will work on every platform/runtime.
/// </summary>
/// <remarks>
/// Description of this bit hacking can be found here:
/// https://cstheory.stackexchange.com/questions/19524/using-the-de-bruijn-sequence-to-find-the-lceil-log-2-v-rceil-of-an-integer
/// </remarks>
/// <param name="value">The value.</param>
private static int Log2SoftwareFallback(uint value)
{
// No AggressiveInlining due to large method size
// Has conventional contract 0->0 (Log(0) is undefined) by default, no need for if checking
// Fill trailing zeros with ones, eg 00010010 becomes 00011111
value |= value >> 01;
value |= value >> 02;
value |= value >> 04;
value |= value >> 08;
value |= value >> 16;
// uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check
return Unsafe.AddByteOffset(
ref MemoryMarshal.GetReference(Log2DeBruijn),
(IntPtr)(int)((value * 0x07C4ACDDu) >> 27)); // uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here
}
#endif
/// <summary>
/// Fast division with ceiling for <see cref="uint"/> numbers.
@ -914,62 +844,6 @@ namespace SixLabors.ImageSharp
/// <returns>Ceiled division result.</returns>
public static uint DivideCeil(uint value, uint divisor) => (value + divisor - 1) / divisor;
/// <summary>
/// Rotates the specified value left by the specified number of bits.
/// </summary>
/// <param name="value">The value to rotate.</param>
/// <param name="offset">The number of bits to rotate with.</param>
/// <returns>The rotated value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateLeft(uint value, int offset)
{
#if SUPPORTS_BITOPERATIONS
return BitOperations.RotateLeft(value, offset);
#else
return RotateLeftSoftwareFallback(value, offset);
#endif
}
#if !SUPPORTS_BITOPERATIONS
/// <summary>
/// Rotates the specified value left by the specified number of bits.
/// </summary>
/// <param name="value">The value to rotate.</param>
/// <param name="offset">The number of bits to rotate with.</param>
/// <returns>The rotated value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateLeftSoftwareFallback(uint value, int offset)
=> (value << offset) | (value >> (32 - offset));
#endif
/// <summary>
/// Rotates the specified value right by the specified number of bits.
/// </summary>
/// <param name="value">The value to rotate.</param>
/// <param name="offset">The number of bits to rotate with.</param>
/// <returns>The rotated value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateRight(uint value, int offset)
{
#if SUPPORTS_BITOPERATIONS
return BitOperations.RotateRight(value, offset);
#else
return RotateRightSoftwareFallback(value, offset);
#endif
}
#if !SUPPORTS_BITOPERATIONS
/// <summary>
/// Rotates the specified value right by the specified number of bits.
/// </summary>
/// <param name="value">The value to rotate.</param>
/// <param name="offset">The number of bits to rotate with.</param>
/// <returns>The rotated value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint RotateRightSoftwareFallback(uint value, int offset)
=> (value >> offset) | (value << (32 - offset));
#endif
/// <summary>
/// Tells whether input value is outside of the given range.
/// </summary>

32
src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs

@ -1,32 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Provides information about the .NET runtime installation.
/// Many methods defer to <see cref="RuntimeInformation"/> when available.
/// </summary>
internal static class RuntimeEnvironment
{
private static readonly Lazy<bool> IsNetCoreLazy = new Lazy<bool>(() => FrameworkDescription.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase));
/// <summary>
/// Gets a value indicating whether the .NET installation is .NET Core 3.1 or lower.
/// </summary>
public static bool IsNetCore => IsNetCoreLazy.Value;
/// <summary>
/// Gets the name of the .NET installation on which an app is running.
/// </summary>
public static string FrameworkDescription => RuntimeInformation.FrameworkDescription;
/// <summary>
/// Indicates whether the current application is running on the specified platform.
/// </summary>
public static bool IsOSPlatform(OSPlatform osPlatform) => RuntimeInformation.IsOSPlatform(osPlatform);
}
}

46
src/ImageSharp/Common/Helpers/RuntimeUtility.cs

@ -0,0 +1,46 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Common.Helpers
{
/// <summary>
/// A helper class that with utility methods for dealing with references, and other low-level details.
/// </summary>
internal static class RuntimeUtility
{
// Tuple swap uses 2 more IL bytes
#pragma warning disable IDE0180 // Use tuple to swap values
/// <summary>
/// Swaps the two references.
/// </summary>
/// <typeparam name="T">The type to swap.</typeparam>
/// <param name="a">The first item.</param>
/// <param name="b">The second item.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Swap<T>(ref T a, ref T b)
{
T tmp = a;
a = b;
b = tmp;
}
/// <summary>
/// Swaps the two references.
/// </summary>
/// <typeparam name="T">The type to swap.</typeparam>
/// <param name="a">The first item.</param>
/// <param name="b">The second item.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Swap<T>(ref Span<T> a, ref Span<T> b)
{
// Tuple swap uses 2 more IL bytes
Span<T> tmp = a;
a = b;
b = tmp;
}
#pragma warning restore IDE0180 // Use tuple to swap values
}
}

7
src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs

@ -3,6 +3,7 @@
using System;
using System.Buffers.Binary;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -157,7 +158,7 @@ namespace SixLabors.ImageSharp
// packed = [W Z Y X]
// ROTR(8, packedArgb) = [Y Z W X]
Unsafe.Add(ref dBase, i) = Numerics.RotateRight(packed, 8);
Unsafe.Add(ref dBase, i) = BitOperations.RotateRight(packed, 8);
}
}
}
@ -188,7 +189,7 @@ namespace SixLabors.ImageSharp
// tmp1 + tmp3 = [W X Y Z]
uint tmp1 = packed & 0xFF00FF00;
uint tmp2 = packed & 0x00FF00FF;
uint tmp3 = Numerics.RotateLeft(tmp2, 16);
uint tmp3 = BitOperations.RotateLeft(tmp2, 16);
Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
}
@ -221,7 +222,7 @@ namespace SixLabors.ImageSharp
// tmp1 + tmp3 = [Y Z W X]
uint tmp1 = packed & 0x00FF00FF;
uint tmp2 = packed & 0xFF00FF00;
uint tmp3 = Numerics.RotateLeft(tmp2, 16);
uint tmp3 = BitOperations.RotateLeft(tmp2, 16);
Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
}

216
src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs

@ -1,216 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Tuples;
// ReSharper disable MemberHidesStaticFromOuterClass
namespace SixLabors.ImageSharp
{
internal static partial class SimdUtils
{
/// <summary>
/// Implementation with 256bit / AVX2 intrinsics NOT depending on newer API-s (Vector.Widen etc.)
/// </summary>
public static class BasicIntrinsics256
{
public static bool IsAvailable { get; } = HasVector8;
#if !SUPPORTS_EXTENDED_INTRINSICS
/// <summary>
/// <see cref="ByteToNormalizedFloat"/> as many elements as possible, slicing them down (keeping the remainder).
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
internal static void ByteToNormalizedFloatReduce(
ref ReadOnlySpan<byte> source,
ref Span<float> dest)
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
if (!IsAvailable)
{
return;
}
int remainder = Numerics.Modulo8(source.Length);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
{
ByteToNormalizedFloat(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount));
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
}
}
/// <summary>
/// <see cref="NormalizedFloatToByteSaturate"/> as many elements as possible, slicing them down (keeping the remainder).
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
internal static void NormalizedFloatToByteSaturateReduce(
ref ReadOnlySpan<float> source,
ref Span<byte> dest)
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
if (!IsAvailable)
{
return;
}
int remainder = Numerics.Modulo8(source.Length);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
{
NormalizedFloatToByteSaturate(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount));
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
}
}
#endif
/// <summary>
/// SIMD optimized implementation for <see cref="SimdUtils.ByteToNormalizedFloat"/>.
/// Works only with span Length divisible by 8.
/// Implementation adapted from:
/// http://lolengine.net/blog/2011/3/20/understanding-fast-float-integer-conversions
/// http://stackoverflow.com/a/536278
/// </summary>
internal static void ByteToNormalizedFloat(ReadOnlySpan<byte> source, Span<float> dest)
{
VerifyHasVector8(nameof(ByteToNormalizedFloat));
VerifySpanInput(source, dest, 8);
var bVec = new Vector<float>(256.0f / 255.0f);
var magicFloat = new Vector<float>(32768.0f);
var magicInt = new Vector<uint>(1191182336); // reinterpreted value of 32768.0f
var mask = new Vector<uint>(255);
ref Octet<byte> sourceBase = ref Unsafe.As<byte, Octet<byte>>(ref MemoryMarshal.GetReference(source));
ref Octet<uint> destBaseAsWideOctet = ref Unsafe.As<float, Octet<uint>>(ref MemoryMarshal.GetReference(dest));
ref Vector<float> destBaseAsFloat = ref Unsafe.As<Octet<uint>, Vector<float>>(ref destBaseAsWideOctet);
int n = dest.Length / 8;
for (int i = 0; i < n; i++)
{
ref Octet<byte> s = ref Unsafe.Add(ref sourceBase, i);
ref Octet<uint> d = ref Unsafe.Add(ref destBaseAsWideOctet, i);
d.LoadFrom(ref s);
}
for (int i = 0; i < n; i++)
{
ref Vector<float> df = ref Unsafe.Add(ref destBaseAsFloat, i);
var vi = Vector.AsVectorUInt32(df);
vi &= mask;
vi |= magicInt;
var vf = Vector.AsVectorSingle(vi);
vf = (vf - magicFloat) * bVec;
df = vf;
}
}
/// <summary>
/// Implementation of <see cref="SimdUtils.NormalizedFloatToByteSaturate"/> which is faster on older runtimes.
/// </summary>
internal static void NormalizedFloatToByteSaturate(ReadOnlySpan<float> source, Span<byte> dest)
{
VerifyHasVector8(nameof(NormalizedFloatToByteSaturate));
VerifySpanInput(source, dest, 8);
if (source.Length == 0)
{
return;
}
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(source));
ref Octet<byte> destBase = ref Unsafe.As<byte, Octet<byte>>(ref MemoryMarshal.GetReference(dest));
int n = source.Length / 8;
var magick = new Vector<float>(32768.0f);
var scale = new Vector<float>(255f) / new Vector<float>(256f);
// need to copy to a temporary struct, because
// SimdUtils.Octet<uint> temp = Unsafe.As<Vector<float>, SimdUtils.Octet<uint>>(ref x)
// does not work. TODO: This might be a CoreClr bug, need to ask/report
var temp = default(Octet<uint>);
ref Vector<float> tempRef = ref Unsafe.As<Octet<uint>, Vector<float>>(ref temp);
for (int i = 0; i < n; i++)
{
// union { float f; uint32_t i; } u;
// u.f = 32768.0f + x * (255.0f / 256.0f);
// return (uint8_t)u.i;
Vector<float> x = Unsafe.Add(ref srcBase, i);
x = Vector.Max(x, Vector<float>.Zero);
x = Vector.Min(x, Vector<float>.One);
x = (x * scale) + magick;
tempRef = x;
ref Octet<byte> d = ref Unsafe.Add(ref destBase, i);
d.LoadFrom(ref temp);
}
}
/// <summary>
/// Convert all <see cref="float"/> values normalized into [0..1] from 'source'
/// into 'dest' buffer of <see cref="byte"/>. The values are scaled up into [0-255] and rounded.
/// This implementation is SIMD optimized and works only when span Length is divisible by 8.
/// Based on:
/// <see>
/// <cref>http://lolengine.net/blog/2011/3/20/understanding-fast-float-integer-conversions</cref>
/// </see>
/// </summary>
internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan<float> source, Span<byte> dest)
{
VerifyHasVector8(nameof(BulkConvertNormalizedFloatToByte));
VerifySpanInput(source, dest, 8);
if (source.Length == 0)
{
return;
}
ref Vector<float> srcBase = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(source));
ref Octet<byte> destBase = ref Unsafe.As<byte, Octet<byte>>(ref MemoryMarshal.GetReference(dest));
int n = source.Length / 8;
var magick = new Vector<float>(32768.0f);
var scale = new Vector<float>(255f) / new Vector<float>(256f);
// need to copy to a temporary struct, because
// SimdUtils.Octet<uint> temp = Unsafe.As<Vector<float>, SimdUtils.Octet<uint>>(ref x)
// does not work. TODO: This might be a CoreClr bug, need to ask/report
var temp = default(Octet<uint>);
ref Vector<float> tempRef = ref Unsafe.As<Octet<uint>, Vector<float>>(ref temp);
for (int i = 0; i < n; i++)
{
// union { float f; uint32_t i; } u;
// u.f = 32768.0f + x * (255.0f / 256.0f);
// return (uint8_t)u.i;
Vector<float> x = Unsafe.Add(ref srcBase, i);
x = (x * scale) + magick;
tempRef = x;
ref Octet<byte> d = ref Unsafe.Add(ref destBase, i);
d.LoadFrom(ref temp);
}
}
}
}
}

35
src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs

@ -21,12 +21,7 @@ namespace SixLabors.ImageSharp
/// </summary>
public static class ExtendedIntrinsics
{
public static bool IsAvailable { get; } =
#if SUPPORTS_EXTENDED_INTRINSICS
Vector.IsHardwareAccelerated;
#else
false;
#endif
public static bool IsAvailable { get; } = Vector.IsHardwareAccelerated;
/// <summary>
/// Widen and convert a vector of <see cref="short"/> values into 2 vectors of <see cref="float"/>-s.
@ -62,10 +57,10 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
ByteToNormalizedFloat(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount));
ByteToNormalizedFloat(source[..adjustedCount], dest[..adjustedCount]);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
@ -89,12 +84,10 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
NormalizedFloatToByteSaturate(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount));
NormalizedFloatToByteSaturate(source[..adjustedCount], dest[..adjustedCount]);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
@ -160,12 +153,10 @@ namespace SixLabors.ImageSharp
Vector<uint> w2 = ConvertToUInt32(f2);
Vector<uint> w3 = ConvertToUInt32(f3);
Vector<ushort> u0 = Vector.Narrow(w0, w1);
Vector<ushort> u1 = Vector.Narrow(w2, w3);
var u0 = Vector.Narrow(w0, w1);
var u1 = Vector.Narrow(w2, w3);
Vector<byte> b = Vector.Narrow(u0, u1);
Unsafe.Add(ref destBase, i) = b;
Unsafe.Add(ref destBase, i) = Vector.Narrow(u0, u1);
}
}
@ -176,15 +167,15 @@ namespace SixLabors.ImageSharp
vf *= maxBytes;
vf += new Vector<float>(0.5f);
vf = Vector.Min(Vector.Max(vf, Vector<float>.Zero), maxBytes);
Vector<int> vi = Vector.ConvertToInt32(vf);
var vi = Vector.ConvertToInt32(vf);
return Vector.AsVectorUInt32(vi);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector<float> ConvertToSingle(Vector<uint> u)
{
Vector<int> vi = Vector.AsVectorInt32(u);
Vector<float> v = Vector.ConvertToSingle(vi);
var vi = Vector.AsVectorInt32(u);
var v = Vector.ConvertToSingle(vi);
v *= new Vector<float>(1f / 255f);
return v;
}

20
src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs

@ -33,12 +33,10 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
ByteToNormalizedFloat(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount));
ByteToNormalizedFloat(source[..adjustedCount], dest[..adjustedCount]);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
@ -58,11 +56,11 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
NormalizedFloatToByteSaturate(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount));
source[..adjustedCount],
dest[..adjustedCount]);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
@ -83,7 +81,7 @@ namespace SixLabors.ImageSharp
ref ByteVector4 sBase = ref Unsafe.As<byte, ByteVector4>(ref MemoryMarshal.GetReference(source));
ref Vector4 dBase = ref Unsafe.As<float, Vector4>(ref MemoryMarshal.GetReference(dest));
const float Scale = 1f / 255f;
const float scale = 1f / 255f;
Vector4 d = default;
for (int i = 0; i < count; i++)
@ -93,7 +91,7 @@ namespace SixLabors.ImageSharp
d.Y = s.Y;
d.Z = s.Z;
d.W = s.W;
d *= Scale;
d *= scale;
Unsafe.Add(ref dBase, i) = d;
}
}

88
src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -67,12 +66,12 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
Shuffle4(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount),
source[..adjustedCount],
dest[..adjustedCount],
control);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
}
@ -101,12 +100,12 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
Shuffle4(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount),
source[..adjustedCount],
dest[..adjustedCount],
control);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
}
@ -133,12 +132,12 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
Shuffle3(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount),
source[..adjustedCount],
dest[..adjustedCount],
control);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
}
@ -166,12 +165,12 @@ namespace SixLabors.ImageSharp
if (sourceCount > 0)
{
Pad3Shuffle4(
source.Slice(0, sourceCount),
dest.Slice(0, destCount),
source[..sourceCount],
dest[..destCount],
control);
source = source.Slice(sourceCount);
dest = dest.Slice(destCount);
source = source[sourceCount..];
dest = dest[destCount..];
}
}
}
@ -199,12 +198,12 @@ namespace SixLabors.ImageSharp
if (sourceCount > 0)
{
Shuffle4Slice3(
source.Slice(0, sourceCount),
dest.Slice(0, destCount),
source[..sourceCount],
dest[..destCount],
control);
source = source.Slice(sourceCount);
dest = dest.Slice(destCount);
source = source[sourceCount..];
dest = dest[destCount..];
}
}
}
@ -607,10 +606,10 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
ByteToNormalizedFloat(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount));
ByteToNormalizedFloat(source[..adjustedCount], dest[..adjustedCount]);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
}
@ -740,11 +739,11 @@ namespace SixLabors.ImageSharp
if (adjustedCount > 0)
{
NormalizedFloatToByteSaturate(
source.Slice(0, adjustedCount),
dest.Slice(0, adjustedCount));
source[..adjustedCount],
dest[..adjustedCount]);
source = source.Slice(adjustedCount);
dest = dest.Slice(adjustedCount);
source = source[adjustedCount..];
dest = dest[adjustedCount..];
}
}
}
@ -848,13 +847,12 @@ namespace SixLabors.ImageSharp
int count = redChannel.Length / Vector256<byte>.Count;
ref byte control1Bytes = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32);
ref byte control1Bytes = ref MemoryMarshal.GetReference(PermuteMaskEvenOdd8x32);
Vector256<uint> control1 = Unsafe.As<byte, Vector256<uint>>(ref control1Bytes);
ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32);
Vector256<uint> control2 = Unsafe.As<byte, Vector256<uint>>(ref control2Bytes);
Vector256<byte> a = Vector256.Create((byte)255);
var a = Vector256.Create((byte)255);
Vector256<byte> shuffleAlpha = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha));
@ -902,10 +900,10 @@ namespace SixLabors.ImageSharp
}
int slice = count * Vector256<byte>.Count;
redChannel = redChannel.Slice(slice);
greenChannel = greenChannel.Slice(slice);
blueChannel = blueChannel.Slice(slice);
destination = destination.Slice(slice);
redChannel = redChannel[slice..];
greenChannel = greenChannel[slice..];
blueChannel = blueChannel[slice..];
destination = destination[slice..];
}
internal static void PackFromRgbPlanesAvx2Reduce(
@ -920,16 +918,9 @@ namespace SixLabors.ImageSharp
ref Vector256<byte> dBase = ref Unsafe.As<Rgba32, Vector256<byte>>(ref MemoryMarshal.GetReference(destination));
int count = redChannel.Length / Vector256<byte>.Count;
ref byte control1Bytes = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32);
ref byte control1Bytes = ref MemoryMarshal.GetReference(PermuteMaskEvenOdd8x32);
Vector256<uint> control1 = Unsafe.As<byte, Vector256<uint>>(ref control1Bytes);
ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32);
Vector256<uint> control2 = Unsafe.As<byte, Vector256<uint>>(ref control2Bytes);
Vector256<byte> a = Vector256.Create((byte)255);
Vector256<byte> shuffleAlpha = Unsafe.As<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha));
var a = Vector256.Create((byte)255);
for (int i = 0; i < count; i++)
{
@ -961,10 +952,10 @@ namespace SixLabors.ImageSharp
}
int slice = count * Vector256<byte>.Count;
redChannel = redChannel.Slice(slice);
greenChannel = greenChannel.Slice(slice);
blueChannel = blueChannel.Slice(slice);
destination = destination.Slice(slice);
redChannel = redChannel[slice..];
greenChannel = greenChannel[slice..];
blueChannel = blueChannel[slice..];
destination = destination[slice..];
}
internal static void UnpackToRgbPlanesAvx2Reduce(
@ -1012,4 +1003,3 @@ namespace SixLabors.ImageSharp
}
}
}
#endif

26
src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs

@ -4,10 +4,8 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.PixelFormats;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics.X86;
#endif
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp
{
@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp
{
[MethodImpl(InliningOptions.ShortMethod)]
internal static void PackFromRgbPlanes(
Configuration configuration,
ReadOnlySpan<byte> redChannel,
ReadOnlySpan<byte> greenChannel,
ReadOnlySpan<byte> blueChannel,
@ -25,13 +22,11 @@ namespace SixLabors.ImageSharp
DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!");
DebugGuard.IsTrue(destination.Length > redChannel.Length + 2, nameof(destination), "'destination' must contain a padding of 3 elements!");
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported)
{
HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination);
}
else
#endif
{
PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination);
}
@ -41,7 +36,6 @@ namespace SixLabors.ImageSharp
[MethodImpl(InliningOptions.ShortMethod)]
internal static void PackFromRgbPlanes(
Configuration configuration,
ReadOnlySpan<byte> redChannel,
ReadOnlySpan<byte> greenChannel,
ReadOnlySpan<byte> blueChannel,
@ -51,13 +45,11 @@ namespace SixLabors.ImageSharp
DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!");
DebugGuard.IsTrue(destination.Length > redChannel.Length, nameof(destination), "'destination' span should not be shorter than the source channels!");
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported)
{
HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination);
}
else
#endif
{
PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination);
}
@ -125,10 +117,10 @@ namespace SixLabors.ImageSharp
}
int finished = count * 4;
redChannel = redChannel.Slice(finished);
greenChannel = greenChannel.Slice(finished);
blueChannel = blueChannel.Slice(finished);
destination = destination.Slice(finished);
redChannel = redChannel[finished..];
greenChannel = greenChannel[finished..];
blueChannel = blueChannel[finished..];
destination = destination[finished..];
}
private static void PackFromRgbPlanesScalarBatchedReduce(
@ -173,10 +165,10 @@ namespace SixLabors.ImageSharp
}
int finished = count * 4;
redChannel = redChannel.Slice(finished);
greenChannel = greenChannel.Slice(finished);
blueChannel = blueChannel.Slice(finished);
destination = destination.Slice(finished);
redChannel = redChannel[finished..];
greenChannel = greenChannel[finished..];
blueChannel = blueChannel[finished..];
destination = destination[finished..];
}
private static void PackFromRgbPlanesRemainder(

18
src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs

@ -25,9 +25,7 @@ namespace SixLabors.ImageSharp
{
VerifyShuffle4SpanInput(source, dest);
#if SUPPORTS_RUNTIME_INTRINSICS
HwIntrinsics.Shuffle4Reduce(ref source, ref dest, control);
#endif
// Deal with the remainder:
if (source.Length > 0)
@ -52,9 +50,7 @@ namespace SixLabors.ImageSharp
{
VerifyShuffle4SpanInput(source, dest);
#if SUPPORTS_RUNTIME_INTRINSICS
HwIntrinsics.Shuffle4Reduce(ref source, ref dest, shuffle.Control);
#endif
// Deal with the remainder:
if (source.Length > 0)
@ -80,9 +76,7 @@ namespace SixLabors.ImageSharp
// Source length should be smaller than dest length, and divisible by 3.
VerifyShuffle3SpanInput(source, dest);
#if SUPPORTS_RUNTIME_INTRINSICS
HwIntrinsics.Shuffle3Reduce(ref source, ref dest, shuffle.Control);
#endif
// Deal with the remainder:
if (source.Length > 0)
@ -107,9 +101,7 @@ namespace SixLabors.ImageSharp
{
VerifyPad3Shuffle4SpanInput(source, dest);
#if SUPPORTS_RUNTIME_INTRINSICS
HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, shuffle.Control);
#endif
// Deal with the remainder:
if (source.Length > 0)
@ -134,9 +126,7 @@ namespace SixLabors.ImageSharp
{
VerifyShuffle4Slice3SpanInput(source, dest);
#if SUPPORTS_RUNTIME_INTRINSICS
HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, shuffle.Control);
#endif
// Deal with the remainder:
if (source.Length > 0)
@ -266,10 +256,10 @@ namespace SixLabors.ImageSharp
out int p1,
out int p0)
{
p3 = control >> 6 & 0x3;
p2 = control >> 4 & 0x3;
p1 = control >> 2 & 0x3;
p0 = control >> 0 & 0x3;
p3 = (control >> 6) & 0x3;
p2 = (control >> 4) & 0x3;
p1 = (control >> 2) & 0x3;
p0 = (control >> 0) & 0x3;
}
}
}

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

@ -6,11 +6,8 @@ using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.PixelFormats;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
namespace SixLabors.ImageSharp
{
@ -56,8 +53,6 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static Vector<float> FastRound(this Vector<float> v)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported)
{
ref Vector256<float> v256 = ref Unsafe.As<Vector<float>, Vector256<float>>(ref v);
@ -65,7 +60,6 @@ namespace SixLabors.ImageSharp
return Unsafe.As<Vector256<float>, Vector<float>>(ref vRound);
}
else
#endif
{
var magic0 = new Vector<int>(int.MinValue); // 0x80000000
var sgn0 = Vector.AsVectorSingle(magic0);
@ -87,13 +81,8 @@ namespace SixLabors.ImageSharp
internal static void ByteToNormalizedFloat(ReadOnlySpan<byte> source, Span<float> dest)
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
#if SUPPORTS_RUNTIME_INTRINSICS
HwIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest);
#elif SUPPORTS_EXTENDED_INTRINSICS
ExtendedIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest);
#else
BasicIntrinsics256.ByteToNormalizedFloatReduce(ref source, ref dest);
#endif
// Also deals with the remainder from previous conversions:
FallbackIntrinsics128.ByteToNormalizedFloatReduce(ref source, ref dest);
@ -118,13 +107,7 @@ namespace SixLabors.ImageSharp
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
#if SUPPORTS_RUNTIME_INTRINSICS
HwIntrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref dest);
#elif SUPPORTS_EXTENDED_INTRINSICS
ExtendedIntrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref dest);
#else
BasicIntrinsics256.NormalizedFloatToByteSaturateReduce(ref source, ref dest);
#endif
// Also deals with the remainder from previous conversions:
FallbackIntrinsics128.NormalizedFloatToByteSaturateReduce(ref source, ref dest);

3
src/ImageSharp/Common/Helpers/UnitConverter.cs

@ -114,11 +114,10 @@ namespace SixLabors.ImageSharp.Common.Helpers
case PixelResolutionUnit.PixelsPerCentimeter:
break;
case PixelResolutionUnit.PixelsPerMeter:
{
unit = PixelResolutionUnit.PixelsPerCentimeter;
horizontal = MeterToCm(horizontal);
vertical = MeterToCm(vertical);
}
break;
default:

22
src/ImageSharp/Compression/Zlib/Adler32.cs

@ -4,10 +4,8 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
#pragma warning disable IDE0007 // Use implicit type
namespace SixLabors.ImageSharp.Compression.Zlib
@ -29,7 +27,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib
// NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
private const uint NMAX = 5552;
#if SUPPORTS_RUNTIME_INTRINSICS
private const int MinBufferSize = 64;
private const int BlockSize = 1 << 5;
@ -40,7 +37,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, // tap1
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 // tap2
};
#endif
/// <summary>
/// Calculates the Adler32 checksum with the bytes taken from the span.
@ -65,7 +61,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib
return adler;
}
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && buffer.Length >= MinBufferSize)
{
return CalculateAvx2(adler, buffer);
@ -77,13 +72,9 @@ namespace SixLabors.ImageSharp.Compression.Zlib
}
return CalculateScalar(adler, buffer);
#else
return CalculateScalar(adler, buffer);
#endif
}
// Based on https://github.com/chromium/chromium/blob/master/third_party/zlib/adler32_simd.c
#if SUPPORTS_RUNTIME_INTRINSICS
[MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)]
private static unsafe uint CalculateSse(uint adler, ReadOnlySpan<byte> buffer)
{
@ -149,15 +140,15 @@ namespace SixLabors.ImageSharp.Compression.Zlib
v_s2 = Sse2.Add(v_s2, Sse2.ShiftLeftLogical(v_ps, 5));
// Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
const byte S2301 = 0b1011_0001; // A B C D -> B A D C
const byte S1032 = 0b0100_1110; // A B C D -> C D A B
const byte s2301 = 0b1011_0001; // A B C D -> B A D C
const byte s1032 = 0b0100_1110; // A B C D -> C D A B
v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, S1032));
v_s1 = Sse2.Add(v_s1, Sse2.Shuffle(v_s1, s1032));
s1 += v_s1.ToScalar();
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S2301));
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, S1032));
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, s2301));
v_s2 = Sse2.Add(v_s2, Sse2.Shuffle(v_s2, s1032));
s2 = v_s2.ToScalar();
@ -290,7 +281,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib
s2 %= BASE;
}
#endif
[MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)]
private static unsafe uint CalculateScalar(uint adler, ReadOnlySpan<byte> buffer)
@ -301,7 +291,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib
fixed (byte* bufferPtr = buffer)
{
var localBufferPtr = bufferPtr;
byte* localBufferPtr = bufferPtr;
uint length = (uint)buffer.Length;
while (length > 0)

16
src/ImageSharp/Compression/Zlib/Crc32.cs

@ -4,10 +4,8 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
namespace SixLabors.ImageSharp.Compression.Zlib
{
@ -22,7 +20,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib
/// </summary>
public const uint SeedValue = 0U;
#if SUPPORTS_RUNTIME_INTRINSICS
private const int MinBufferSize = 64;
private const int ChunksizeMask = 15;
@ -35,7 +32,6 @@ namespace SixLabors.ImageSharp.Compression.Zlib
0x0163cd6124, 0x0000000000, // k5, k0
0x01db710641, 0x01f7011641 // polynomial
};
#endif
/// <summary>
/// Calculates the CRC checksum with the bytes taken from the span.
@ -60,21 +56,14 @@ namespace SixLabors.ImageSharp.Compression.Zlib
return crc;
}
#if SUPPORTS_RUNTIME_INTRINSICS
if (Sse41.IsSupported && Pclmulqdq.IsSupported && buffer.Length >= MinBufferSize)
{
return ~CalculateSse(~crc, buffer);
}
else
{
return ~CalculateScalar(~crc, buffer);
}
#else
return ~CalculateScalar(~crc, buffer);
#endif
}
#if SUPPORTS_RUNTIME_INTRINSICS
// Based on https://github.com/chromium/chromium/blob/master/third_party/zlib/crc32_simd.c
[MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)]
private static unsafe uint CalculateSse(uint crc, ReadOnlySpan<byte> buffer)
@ -194,11 +183,10 @@ namespace SixLabors.ImageSharp.Compression.Zlib
x1 = Sse2.Xor(x1, x2);
crc = (uint)Sse41.Extract(x1.AsInt32(), 1);
return buffer.Length - chunksize == 0 ? crc : CalculateScalar(crc, buffer.Slice(chunksize));
return buffer.Length - chunksize == 0 ? crc : CalculateScalar(crc, buffer[chunksize..]);
}
}
}
#endif
[MethodImpl(InliningOptions.HotPath | InliningOptions.ShortMethod)]
private static uint CalculateScalar(uint crc, ReadOnlySpan<byte> buffer)

6
src/ImageSharp/Compression/Zlib/DeflaterEngine.cs

@ -276,8 +276,8 @@ namespace SixLabors.ImageSharp.Compression.Zlib
this.lookahead = 0;
this.prevAvailable = false;
this.matchLen = DeflaterConstants.MIN_MATCH - 1;
this.head.Span.Slice(0, DeflaterConstants.HASH_SIZE).Clear();
this.prev.Span.Slice(0, DeflaterConstants.WSIZE).Clear();
this.head.Span[..DeflaterConstants.HASH_SIZE].Clear();
this.prev.Span[..DeflaterConstants.WSIZE].Clear();
}
/// <summary>
@ -286,7 +286,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib
/// <param name="level">The value to set the level to.</param>
public void SetLevel(int level)
{
if ((level < 0) || (level > 9))
if (level is < 0 or > 9)
{
DeflateThrowHelper.ThrowOutOfRange(nameof(level));
}

4
src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs

@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib
break;
}
this.rawStream.Write(this.buffer.Span.Slice(0, deflateCount));
this.rawStream.Write(this.buffer.Span[..deflateCount]);
}
if (!this.deflater.IsNeedingInput)
@ -115,7 +115,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib
break;
}
this.rawStream.Write(this.buffer.Span.Slice(0, len));
this.rawStream.Write(this.buffer.Span[..len]);
}
if (!this.deflater.IsFinished)

2
src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs

@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Compression.Zlib
{
Unsafe.CopyBlockUnaligned(
ref this.buffer.Span[this.end],
ref MemoryMarshal.GetReference(block.Slice(offset)),
ref MemoryMarshal.GetReference(block[offset..]),
unchecked((uint)length));
this.end += length;

2
src/ImageSharp/Configuration.cs

@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp
get => this.maxDegreeOfParallelism;
set
{
if (value == 0 || value < -1)
if (value is 0 or < -1)
{
throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism));
}

7
src/ImageSharp/Diagnostics/MemoryDiagnostics.cs

@ -9,6 +9,7 @@ namespace SixLabors.ImageSharp.Diagnostics
/// <summary>
/// Represents the method to handle <see cref="MemoryDiagnostics.UndisposedAllocation"/>.
/// </summary>
/// <param name="allocationStackTrace">The allocation stack trace.</param>
public delegate void UndisposedAllocationDelegate(string allocationStackTrace);
/// <summary>
@ -85,16 +86,10 @@ namespace SixLabors.ImageSharp.Diagnostics
}
// Schedule on the ThreadPool, to avoid user callback messing up the finalizer thread.
#if NETSTANDARD2_1 || NETCOREAPP2_1_OR_GREATER
ThreadPool.QueueUserWorkItem(
stackTrace => undisposedAllocation?.Invoke(stackTrace),
allocationStackTrace,
preferLocal: false);
#else
ThreadPool.QueueUserWorkItem(
stackTrace => undisposedAllocation?.Invoke((string)stackTrace),
allocationStackTrace);
#endif
}
}
}

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

@ -491,7 +491,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int max = cmd[1];
int bytesToRead = (max + 1) / 2;
var run = new byte[bytesToRead];
byte[] run = new byte[bytesToRead];
this.stream.Read(run, 0, run.Length);
@ -501,13 +501,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
byte twoPixels = run[idx];
if (i % 2 == 0)
{
byte leftPixel = (byte)((twoPixels >> 4) & 0xF);
buffer[count++] = leftPixel;
buffer[count++] = (byte)((twoPixels >> 4) & 0xF);
}
else
{
byte rightPixel = (byte)(twoPixels & 0xF);
buffer[count++] = rightPixel;
buffer[count++] = (byte)(twoPixels & 0xF);
idx++;
}
}
@ -597,11 +595,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
// Take this number of bytes from the stream as uncompressed data.
int length = cmd[1];
var run = new byte[length];
byte[] run = new byte[length];
this.stream.Read(run, 0, run.Length);
run.AsSpan().CopyTo(buffer.Slice(count));
run.AsSpan().CopyTo(buffer[count..]);
count += run.Length;
@ -676,11 +674,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
// Take this number of bytes from the stream as uncompressed data.
int length = cmd[1];
var run = new byte[length * 3];
byte[] run = new byte[length * 3];
this.stream.Read(run, 0, run.Length);
run.AsSpan().CopyTo(buffer.Slice(start: uncompressedPixels * 3));
run.AsSpan().CopyTo(buffer[(uncompressedPixels * 3)..]);
uncompressedPixels += length;
@ -903,13 +901,13 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int offset = 0;
for (int x = 0; x < width; x++)
{
short temp = BinaryPrimitives.ReadInt16LittleEndian(bufferSpan.Slice(offset));
short temp = BinaryPrimitives.ReadInt16LittleEndian(bufferSpan[offset..]);
// Rescale values, so the values range from 0 to 255.
int r = (redMaskBits == 5) ? GetBytesFrom5BitValue((temp & redMask) >> rightShiftRedMask) : GetBytesFrom6BitValue((temp & redMask) >> rightShiftRedMask);
int g = (greenMaskBits == 5) ? GetBytesFrom5BitValue((temp & greenMask) >> rightShiftGreenMask) : GetBytesFrom6BitValue((temp & greenMask) >> rightShiftGreenMask);
int b = (blueMaskBits == 5) ? GetBytesFrom5BitValue((temp & blueMask) >> rightShiftBlueMask) : GetBytesFrom6BitValue((temp & blueMask) >> rightShiftBlueMask);
var rgb = new Rgb24((byte)r, (byte)g, (byte)b);
Rgb24 rgb = new((byte)r, (byte)g, (byte)b);
color.FromRgb24(rgb);
pixelRow[x] = color;
@ -1156,7 +1154,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int offset = 0;
for (int x = 0; x < width; x++)
{
uint temp = BinaryPrimitives.ReadUInt32LittleEndian(bufferSpan.Slice(offset));
uint temp = BinaryPrimitives.ReadUInt32LittleEndian(bufferSpan[offset..]);
if (unusualBitMask)
{
@ -1164,7 +1162,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
uint g = (uint)(temp & greenMask) >> rightShiftGreenMask;
uint b = (uint)(temp & blueMask) >> rightShiftBlueMask;
float alpha = alphaMask != 0 ? invMaxValueAlpha * ((uint)(temp & alphaMask) >> rightShiftAlphaMask) : 1.0f;
var vector4 = new Vector4(
Vector4 vector4 = new(
r * invMaxValueRed,
g * invMaxValueGreen,
b * invMaxValueBlue,
@ -1246,7 +1244,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize);
int headerSize = BinaryPrimitives.ReadInt32LittleEndian(buffer);
if (headerSize < BmpInfoHeader.CoreSize || headerSize > BmpInfoHeader.MaxHeaderSize)
if (headerSize is < BmpInfoHeader.CoreSize or > BmpInfoHeader.MaxHeaderSize)
{
BmpThrowHelper.ThrowNotSupportedException($"ImageSharp does not support this BMP file. HeaderSize is '{headerSize}'.");
}
@ -1277,19 +1275,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp
// color masks for each color channel follow the info header.
if (this.infoHeader.Compression == BmpCompression.BitFields)
{
var bitfieldsBuffer = new byte[12];
byte[] bitfieldsBuffer = new byte[12];
this.stream.Read(bitfieldsBuffer, 0, 12);
Span<byte> data = bitfieldsBuffer.AsSpan();
this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4));
this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]);
this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4));
this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4));
}
else if (this.infoHeader.Compression == BmpCompression.BI_ALPHABITFIELDS)
{
var bitfieldsBuffer = new byte[16];
byte[] bitfieldsBuffer = new byte[16];
this.stream.Read(bitfieldsBuffer, 0, 16);
Span<byte> data = bitfieldsBuffer.AsSpan();
this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4));
this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]);
this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4));
this.infoHeader.BlueMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4));
this.infoHeader.AlphaMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(12, 4));
@ -1396,6 +1394,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <summary>
/// Reads the <see cref="BmpFileHeader"/> and <see cref="BmpInfoHeader"/> from the stream and sets the corresponding fields.
/// </summary>
/// <param name="stream">The input stream.</param>
/// <param name="inverted">Whether the image orientation is inverted.</param>
/// <param name="palette">The color palette.</param>
/// <returns>Bytes per color palette entry. Usually 4 bytes, but in case of Windows 2.x bitmaps or OS/2 1.x bitmaps
/// the bytes per color palette entry's can be 3 bytes instead of 4.</returns>
private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out byte[] palette)

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

@ -160,10 +160,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp
Span<byte> buffer = stackalloc byte[infoHeaderSize];
this.WriteBitmapFileHeader(stream, infoHeaderSize, colorPaletteSize, iccProfileSize, infoHeader, buffer);
WriteBitmapFileHeader(stream, infoHeaderSize, colorPaletteSize, iccProfileSize, infoHeader, buffer);
this.WriteBitmapInfoHeader(stream, infoHeader, buffer, infoHeaderSize);
this.WriteImage(stream, image.Frames.RootFrame);
this.WriteColorProfile(stream, iccProfileData, buffer);
WriteColorProfile(stream, iccProfileData, buffer);
stream.Flush();
}
@ -184,34 +184,33 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int hResolution = 0;
int vResolution = 0;
if (metadata.ResolutionUnits != PixelResolutionUnit.AspectRatio)
if (metadata.ResolutionUnits != PixelResolutionUnit.AspectRatio
&& metadata.HorizontalResolution > 0
&& metadata.VerticalResolution > 0)
{
if (metadata.HorizontalResolution > 0 && metadata.VerticalResolution > 0)
switch (metadata.ResolutionUnits)
{
switch (metadata.ResolutionUnits)
{
case PixelResolutionUnit.PixelsPerInch:
case PixelResolutionUnit.PixelsPerInch:
hResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.HorizontalResolution));
vResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.VerticalResolution));
break;
hResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.HorizontalResolution));
vResolution = (int)Math.Round(UnitConverter.InchToMeter(metadata.VerticalResolution));
break;
case PixelResolutionUnit.PixelsPerCentimeter:
case PixelResolutionUnit.PixelsPerCentimeter:
hResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.HorizontalResolution));
vResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.VerticalResolution));
break;
hResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.HorizontalResolution));
vResolution = (int)Math.Round(UnitConverter.CmToMeter(metadata.VerticalResolution));
break;
case PixelResolutionUnit.PixelsPerMeter:
hResolution = (int)Math.Round(metadata.HorizontalResolution);
vResolution = (int)Math.Round(metadata.VerticalResolution);
case PixelResolutionUnit.PixelsPerMeter:
hResolution = (int)Math.Round(metadata.HorizontalResolution);
vResolution = (int)Math.Round(metadata.VerticalResolution);
break;
}
break;
}
}
var infoHeader = new BmpInfoHeader(
BmpInfoHeader infoHeader = new(
headerSize: infoHeaderSize,
height: height,
width: width,
@ -248,7 +247,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <param name="stream">The stream to write to.</param>
/// <param name="iccProfileData">The color profile data.</param>
/// <param name="buffer">The buffer.</param>
private void WriteColorProfile(Stream stream, byte[] iccProfileData, Span<byte> buffer)
private static void WriteColorProfile(Stream stream, byte[] iccProfileData, Span<byte> buffer)
{
if (iccProfileData != null)
{
@ -257,7 +256,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
stream.Write(iccProfileData);
BinaryPrimitives.WriteInt32LittleEndian(buffer, streamPositionAfterImageData);
stream.Position = BmpFileHeader.Size + 112;
stream.Write(buffer.Slice(0, 4));
stream.Write(buffer[..4]);
}
}
@ -270,9 +269,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <param name="iccProfileSize">The size in bytes of the color profile.</param>
/// <param name="infoHeader">The information header to write.</param>
/// <param name="buffer">The buffer to write to.</param>
private void WriteBitmapFileHeader(Stream stream, int infoHeaderSize, int colorPaletteSize, int iccProfileSize, BmpInfoHeader infoHeader, Span<byte> buffer)
private static void WriteBitmapFileHeader(Stream stream, int infoHeaderSize, int colorPaletteSize, int iccProfileSize, BmpInfoHeader infoHeader, Span<byte> buffer)
{
var fileHeader = new BmpFileHeader(
BmpFileHeader fileHeader = new(
type: BmpConstants.TypeMarkers.Bitmap,
fileSize: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize + iccProfileSize + infoHeader.ImageSize,
reserved: 0,
@ -555,7 +554,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
if (pixelRowSpan.Length % 2 != 0)
{
stream.WriteByte((byte)((pixelRowSpan[pixelRowSpan.Length - 1] << 4) | 0));
stream.WriteByte((byte)((pixelRowSpan[^1] << 4) | 0));
}
for (int i = 0; i < rowPadding; i++)
@ -675,7 +674,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
where TPixel : unmanaged, IPixel<TPixel>
{
int quantizedColorBytes = quantizedColorPalette.Length * 4;
PixelOperations<TPixel>.Instance.ToBgra32(this.configuration, quantizedColorPalette, MemoryMarshal.Cast<byte, Bgra32>(colorPalette.Slice(0, quantizedColorBytes)));
PixelOperations<TPixel>.Instance.ToBgra32(this.configuration, quantizedColorPalette, MemoryMarshal.Cast<byte, Bgra32>(colorPalette[..quantizedColorBytes]));
Span<uint> colorPaletteAsUInt = MemoryMarshal.Cast<byte, uint>(colorPalette);
for (int i = 0; i < colorPaletteAsUInt.Length; i++)
{

25
src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs

@ -308,7 +308,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <returns>The parsed header.</returns>
/// <seealso href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd183372.aspx"/>
public static BmpInfoHeader ParseCore(ReadOnlySpan<byte> data) => new(
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)),
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]),
width: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(4, 2)),
height: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(6, 2)),
planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(8, 2)),
@ -322,7 +322,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <returns>The parsed header.</returns>
/// <seealso href="https://www.fileformat.info/format/os2bmp/egff.htm"/>
public static BmpInfoHeader ParseOs22Short(ReadOnlySpan<byte> data) => new(
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)),
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]),
width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)),
height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)),
planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)),
@ -335,7 +335,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <returns>The parsed header.</returns>
/// <seealso href="http://www.fileformat.info/format/bmp/egff.htm"/>
public static BmpInfoHeader ParseV3(ReadOnlySpan<byte> data) => new(
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)),
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]),
width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)),
height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)),
planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)),
@ -356,7 +356,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <returns>The parsed header.</returns>
/// <seealso href="https://forums.adobe.com/message/3272950#3272950"/>
public static BmpInfoHeader ParseAdobeV3(ReadOnlySpan<byte> data, bool withAlpha = true) => new(
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)),
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]),
width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)),
height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)),
planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)),
@ -382,18 +382,16 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <seealso href="https://www.fileformat.info/format/os2bmp/egff.htm"/>
public static BmpInfoHeader ParseOs2Version2(ReadOnlySpan<byte> data)
{
var infoHeader = new BmpInfoHeader(
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)),
BmpInfoHeader infoHeader = new(
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]),
width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)),
height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)),
planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)),
bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2)));
int compression = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(16, 4));
// The compression value in OS/2 bitmap has a different meaning than in windows bitmaps.
// Map the OS/2 value to the windows values.
switch (compression)
switch (BinaryPrimitives.ReadInt32LittleEndian(data.Slice(16, 4)))
{
case 0:
infoHeader.Compression = BmpCompression.RGB;
@ -430,7 +428,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <returns>The parsed header.</returns>
/// <seealso href="http://www.fileformat.info/format/bmp/egff.htm"/>
public static BmpInfoHeader ParseV4(ReadOnlySpan<byte> data) => new(
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)),
headerSize: BinaryPrimitives.ReadInt32LittleEndian(data[..4]),
width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)),
height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)),
planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)),
@ -465,11 +463,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <param name="data">The data to parse.</param>
/// <returns>The parsed header.</returns>
/// <seealso href="https://docs.microsoft.com/de-de/windows/win32/api/wingdi/ns-wingdi-bitmapv5header?redirectedfrom=MSDN"/>
/// <exception cref="ArgumentException">Invalid size.</exception>
public static BmpInfoHeader ParseV5(ReadOnlySpan<byte> data)
{
if (data.Length < SizeV5)
{
throw new ArgumentException(nameof(data), $"Must be {SizeV5} bytes. Was {data.Length} bytes.");
throw new ArgumentException($"Must be {SizeV5} bytes. Was {data.Length} bytes.", nameof(data));
}
return MemoryMarshal.Cast<byte, BmpInfoHeader>(data)[0];
@ -482,7 +481,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public void WriteV3Header(Span<byte> buffer)
{
buffer.Clear();
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(0, 4), SizeV3);
BinaryPrimitives.WriteInt32LittleEndian(buffer[..4], SizeV3);
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(4, 4), this.Width);
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(8, 4), this.Height);
BinaryPrimitives.WriteInt16LittleEndian(buffer.Slice(12, 2), this.Planes);
@ -502,7 +501,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
public void WriteV4Header(Span<byte> buffer)
{
buffer.Clear();
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(0, 4), SizeV4);
BinaryPrimitives.WriteInt32LittleEndian(buffer[..4], SizeV4);
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(4, 4), this.Width);
BinaryPrimitives.WriteInt32LittleEndian(buffer.Slice(8, 4), this.Height);
BinaryPrimitives.WriteInt16LittleEndian(buffer.Slice(12, 2), this.Planes);

4
src/ImageSharp/Formats/DecoderOptions.cs

@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats
/// <summary>
/// Gets or sets the target size to decode the image into.
/// </summary>
public Size? TargetSize { get; set; } = null;
public Size? TargetSize { get; set; }
/// <summary>
/// Gets or sets the sampler to use when resizing during decoding.
@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Formats
/// <summary>
/// Gets or sets a value indicating whether to ignore encoded metadata when decoding.
/// </summary>
public bool SkipMetadata { get; set; } = false;
public bool SkipMetadata { get; set; }
/// <summary>
/// Gets or sets the maximum number of image frames to decode, inclusive.

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

@ -108,10 +108,10 @@ namespace SixLabors.ImageSharp.Formats.Gif
this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length);
// Write the header.
this.WriteHeader(stream);
WriteHeader(stream);
// Write the LSD.
int index = this.GetTransparentIndex(quantized);
int index = GetTransparentIndex(quantized);
this.WriteLogicalScreenDescriptor(metadata, image.Width, image.Height, index, useGlobalTable, stream);
if (useGlobalTable)
@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (previousFrame != null && previousMeta.ColorTableLength != frameMetadata.ColorTableLength
&& frameMetadata.ColorTableLength > 0)
{
var options = new QuantizerOptions
QuantizerOptions options = new()
{
Dither = this.quantizer.Options.Dither,
DitherScale = this.quantizer.Options.DitherScale,
@ -211,7 +211,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length);
this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream);
this.WriteGraphicalControlExtension(frameMetadata, GetTransparentIndex(quantized), stream);
this.WriteImageDescriptor(frame, true, stream);
this.WriteColorTable(quantized, stream);
this.WriteImageData(quantized, stream);
@ -231,7 +231,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <returns>
/// The <see cref="int"/>.
/// </returns>
private int GetTransparentIndex<TPixel>(IndexedImageFrame<TPixel> quantized)
private static int GetTransparentIndex<TPixel>(IndexedImageFrame<TPixel> quantized)
where TPixel : unmanaged, IPixel<TPixel>
{
// Transparent pixels are much more likely to be found at the end of a palette.
@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary>
/// <param name="stream">The stream to write to.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void WriteHeader(Stream stream) => stream.Write(GifConstants.MagicNumber);
private static void WriteHeader(Stream stream) => stream.Write(GifConstants.MagicNumber);
/// <summary>
/// Writes the logical screen descriptor to the stream.
@ -308,7 +308,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
}
var descriptor = new GifLogicalScreenDescriptor(
GifLogicalScreenDescriptor descriptor = new(
width: (ushort)width,
height: (ushort)height,
packed: packedValue,
@ -332,14 +332,14 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Application Extension: Loop repeat count.
if (frameCount > 1 && repeatCount != 1)
{
var loopingExtension = new GifNetscapeLoopingApplicationExtension(repeatCount);
GifNetscapeLoopingApplicationExtension loopingExtension = new(repeatCount);
this.WriteExtension(loopingExtension, stream);
}
// Application Extension: XMP Profile.
if (xmpProfile != null)
{
var xmpExtension = new GifXmpApplicationExtension(xmpProfile.Data);
GifXmpApplicationExtension xmpExtension = new(xmpProfile.Data);
this.WriteExtension(xmpExtension, stream);
}
}
@ -411,7 +411,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
disposalMethod: metadata.DisposalMethod,
transparencyFlag: transparencyIndex > -1);
var extension = new GifGraphicControlExtension(
GifGraphicControlExtension extension = new(
packed: packedValue,
delayTime: (ushort)metadata.FrameDelay,
transparencyIndex: unchecked((byte)transparencyIndex));
@ -422,6 +422,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// Writes the provided extension to the stream.
/// </summary>
/// <typeparam name="TGifExtension">The type of gif extension.</typeparam>
/// <param name="extension">The extension to write to the stream.</param>
/// <param name="stream">The stream to write to.</param>
private void WriteExtension<TGifExtension>(TGifExtension extension, Stream stream)
@ -448,7 +449,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
extensionBuffer[0] = GifConstants.ExtensionIntroducer;
extensionBuffer[1] = extension.Label;
extension.WriteTo(extensionBuffer.Slice(2));
extension.WriteTo(extensionBuffer[2..]);
extensionBuffer[extensionSize + 2] = GifConstants.Terminator;
@ -472,7 +473,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
sortFlag: false,
localColorTableSize: this.bitDepth - 1);
var descriptor = new GifImageDescriptor(
GifImageDescriptor descriptor = new(
left: 0,
top: 0,
width: (ushort)image.Width,
@ -517,7 +518,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
private void WriteImageData<TPixel>(IndexedImageFrame<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>
{
using var encoder = new LzwEncoder(this.memoryAllocator, (byte)this.bitDepth);
using LzwEncoder encoder = new(this.memoryAllocator, (byte)this.bitDepth);
encoder.Encode(((IPixelSource)image).PixelBuffer, stream);
}
}

2
src/ImageSharp/Formats/Gif/Sections/GifImageDescriptor.cs

@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
buffer[0] = GifConstants.ImageDescriptorLabel;
ref GifImageDescriptor dest = ref Unsafe.As<byte, GifImageDescriptor>(ref MemoryMarshal.GetReference(buffer.Slice(1)));
ref GifImageDescriptor dest = ref Unsafe.As<byte, GifImageDescriptor>(ref MemoryMarshal.GetReference(buffer[1..]));
dest = this;
}

2
src/ImageSharp/Formats/Gif/Sections/GifNetscapeLoopingApplicationExtension.cs

@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
public static GifNetscapeLoopingApplicationExtension Parse(ReadOnlySpan<byte> buffer)
{
ushort repeatCount = BinaryPrimitives.ReadUInt16LittleEndian(buffer.Slice(0, 2));
ushort repeatCount = BinaryPrimitives.ReadUInt16LittleEndian(buffer[..2]);
return new GifNetscapeLoopingApplicationExtension(repeatCount);
}

4
src/ImageSharp/Formats/Gif/Sections/GifXmpApplicationExtension.cs

@ -55,11 +55,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Write "XMP DataXMP"
ReadOnlySpan<byte> idBytes = GifConstants.XmpApplicationIdentificationBytes;
idBytes.CopyTo(buffer.Slice(bytesWritten));
idBytes.CopyTo(buffer[bytesWritten..]);
bytesWritten += idBytes.Length;
// XMP Data itself
this.Data.CopyTo(buffer.Slice(bytesWritten));
this.Data.CopyTo(buffer[bytesWritten..]);
bytesWritten += this.Data.Length;
// Write the Magic Trailer

2
src/ImageSharp/Formats/ImageFormatManager.cs

@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Formats
if (extension[0] == '.')
{
extension = extension.Substring(1);
extension = extension[1..];
}
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));

2
src/ImageSharp/Formats/Jpeg/Components/Block8x8.Intrinsic.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
@ -36,4 +35,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
public Vector256<short> V67;
}
}
#endif

68
src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs

@ -5,11 +5,10 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
using System.Text;
using SixLabors.ImageSharp.Common.Helpers;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components
{
@ -188,7 +187,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
[MethodImpl(InliningOptions.ShortMethod)]
public nint GetLastNonZeroIndex()
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported)
{
const int equalityMask = unchecked((int)0b1111_1111_1111_1111_1111_1111_1111_1111);
@ -222,7 +220,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
return -1;
}
else
#endif
{
nint index = Size - 1;
ref short elemRef = ref Unsafe.As<Block8x8, short>(ref this);
@ -245,53 +242,46 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
ref short elemRef = ref Unsafe.As<Block8x8, short>(ref this);
// row #0
Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8));
Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16));
Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24));
Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32));
Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40));
Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48));
Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56));
// row #1
Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17));
Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25));
Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33));
Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41));
Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49));
Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57));
// row #2
Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26));
Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34));
Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42));
Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50));
Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58));
// row #3
Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35));
Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43));
Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51));
Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59));
// row #4
Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44));
Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52));
Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60));
// row #5
Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53));
Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61));
// row #6
Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62));
static void Swap(ref short a, ref short b)
{
short tmp = a;
a = b;
b = tmp;
}
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62));
}
/// <summary>

4
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Intrinsic.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
@ -43,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
ref Vector256<float> bBase = ref b.V0;
ref Vector256<short> destRef = ref dest.V01;
Vector256<int> multiplyIntoInt16ShuffleMask = Vector256.Create(0, 1, 4, 5, 2, 3, 6, 7);
var multiplyIntoInt16ShuffleMask = Vector256.Create(0, 1, 4, 5, 2, 3, 6, 7);
for (nint i = 0; i < 8; i += 2)
{
@ -145,4 +144,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
#endif

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

@ -5,11 +5,10 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
using System.Text;
using SixLabors.ImageSharp.Common.Helpers;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Formats.Jpeg.Components
@ -160,10 +159,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
[MethodImpl(InliningOptions.ShortMethod)]
public void MultiplyInPlace(float value)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported)
{
var valueVec = Vector256.Create(value);
Vector256<float> valueVec = Vector256.Create(value);
this.V0 = Avx.Multiply(this.V0, valueVec);
this.V1 = Avx.Multiply(this.V1, valueVec);
this.V2 = Avx.Multiply(this.V2, valueVec);
@ -174,9 +172,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
this.V7 = Avx.Multiply(this.V7, valueVec);
}
else
#endif
{
var valueVec = new Vector4(value);
Vector4 valueVec = new(value);
this.V0L *= valueVec;
this.V0R *= valueVec;
this.V1L *= valueVec;
@ -199,10 +196,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Multiply all elements of the block by the corresponding elements of 'other'.
/// </summary>
/// <param name="other">The other block.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public unsafe void MultiplyInPlace(ref Block8x8F other)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported)
{
this.V0 = Avx.Multiply(this.V0, other.V0);
@ -215,7 +212,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
this.V7 = Avx.Multiply(this.V7, other.V7);
}
else
#endif
{
this.V0L *= other.V0L;
this.V0R *= other.V0R;
@ -243,10 +239,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
[MethodImpl(InliningOptions.ShortMethod)]
public void AddInPlace(float value)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported)
{
var valueVec = Vector256.Create(value);
Vector256<float> valueVec = Vector256.Create(value);
this.V0 = Avx.Add(this.V0, valueVec);
this.V1 = Avx.Add(this.V1, valueVec);
this.V2 = Avx.Add(this.V2, valueVec);
@ -257,9 +252,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
this.V7 = Avx.Add(this.V7, valueVec);
}
else
#endif
{
var valueVec = new Vector4(value);
Vector4 valueVec = new(value);
this.V0L += valueVec;
this.V0R += valueVec;
this.V1L += valueVec;
@ -287,7 +281,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <param name="qt">The quantization table.</param>
public static void Quantize(ref Block8x8F block, ref Block8x8 dest, ref Block8x8F qt)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported)
{
MultiplyIntoInt16_Avx2(ref block, ref qt, ref dest);
@ -299,7 +292,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
ZigZag.ApplyTransposingZigZagOrderingSsse3(ref dest);
}
else
#endif
{
for (int i = 0; i < Size; i++)
{
@ -339,6 +331,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Level shift by +maximum/2, clip to [0..maximum], and round all the values in the block.
/// </summary>
/// <param name="maximum">The maximum value.</param>
public void NormalizeColorsAndRoundInPlace(float maximum)
{
if (SimdUtils.HasVector8)
@ -379,13 +372,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
[MethodImpl(InliningOptions.ShortMethod)]
public void LoadFrom(ref Block8x8 source)
{
#if SUPPORTS_EXTENDED_INTRINSICS
if (SimdUtils.HasVector8)
{
this.LoadFromInt16ExtendedAvx2(ref source);
return;
}
#endif
this.LoadFromInt16Scalar(ref source);
}
@ -427,12 +419,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <param name="value">Value to compare to.</param>
public bool EqualsToScalar(int value)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported)
{
const int equalityMask = unchecked((int)0b1111_1111_1111_1111_1111_1111_1111_1111);
var targetVector = Vector256.Create(value);
Vector256<int> targetVector = Vector256.Create(value);
ref Vector256<float> blockStride = ref this.V0;
for (int i = 0; i < RowCount; i++)
@ -446,20 +437,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
return true;
}
#endif
{
ref float scalars = ref Unsafe.As<Block8x8F, float>(ref this);
for (int i = 0; i < Size; i++)
ref float scalars = ref Unsafe.As<Block8x8F, float>(ref this);
for (int i = 0; i < Size; i++)
{
if ((int)Unsafe.Add(ref scalars, i) != value)
{
if ((int)Unsafe.Add(ref scalars, i) != value)
{
return false;
}
return false;
}
return true;
}
return true;
}
/// <inheritdoc />
@ -481,20 +470,46 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
&& this.V7L == other.V7L
&& this.V7R == other.V7R;
/// <inheritdoc />
public override bool Equals(object obj) => this.Equals((Block8x8F)obj);
/// <inheritdoc />
public override int GetHashCode()
{
int left = HashCode.Combine(
this.V0L,
this.V1L,
this.V2L,
this.V3L,
this.V4L,
this.V5L,
this.V6L,
this.V7L);
int right = HashCode.Combine(
this.V0R,
this.V1R,
this.V2R,
this.V3R,
this.V4R,
this.V5R,
this.V6R,
this.V7R);
return HashCode.Combine(left, right);
}
/// <inheritdoc />
public override string ToString()
{
var sb = new StringBuilder();
StringBuilder sb = new();
sb.Append('[');
for (int i = 0; i < Size - 1; i++)
{
sb.Append(this[i]);
sb.Append(',');
sb.Append(this[i]).Append(',');
}
sb.Append(this[Size - 1]);
sb.Append(']');
sb.Append(this[Size - 1]).Append(']');
return sb.ToString();
}
@ -504,13 +519,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
[MethodImpl(InliningOptions.ShortMethod)]
public void TransposeInplace()
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported)
{
this.TransposeInplace_Avx();
}
else
#endif
{
this.TransposeInplace_Scalar();
}
@ -525,53 +538,46 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
ref float elemRef = ref Unsafe.As<Block8x8F, float>(ref this);
// row #0
Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8));
Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16));
Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24));
Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32));
Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40));
Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48));
Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 1), ref Unsafe.Add(ref elemRef, 8));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 2), ref Unsafe.Add(ref elemRef, 16));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 3), ref Unsafe.Add(ref elemRef, 24));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 4), ref Unsafe.Add(ref elemRef, 32));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 5), ref Unsafe.Add(ref elemRef, 40));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 6), ref Unsafe.Add(ref elemRef, 48));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 7), ref Unsafe.Add(ref elemRef, 56));
// row #1
Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17));
Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25));
Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33));
Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41));
Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49));
Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 10), ref Unsafe.Add(ref elemRef, 17));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 11), ref Unsafe.Add(ref elemRef, 25));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 12), ref Unsafe.Add(ref elemRef, 33));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 13), ref Unsafe.Add(ref elemRef, 41));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 14), ref Unsafe.Add(ref elemRef, 49));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 15), ref Unsafe.Add(ref elemRef, 57));
// row #2
Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26));
Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34));
Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42));
Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50));
Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 19), ref Unsafe.Add(ref elemRef, 26));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 20), ref Unsafe.Add(ref elemRef, 34));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 21), ref Unsafe.Add(ref elemRef, 42));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 22), ref Unsafe.Add(ref elemRef, 50));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 23), ref Unsafe.Add(ref elemRef, 58));
// row #3
Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35));
Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43));
Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51));
Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 28), ref Unsafe.Add(ref elemRef, 35));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 29), ref Unsafe.Add(ref elemRef, 43));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 30), ref Unsafe.Add(ref elemRef, 51));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 31), ref Unsafe.Add(ref elemRef, 59));
// row #4
Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44));
Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52));
Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 37), ref Unsafe.Add(ref elemRef, 44));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 38), ref Unsafe.Add(ref elemRef, 52));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 39), ref Unsafe.Add(ref elemRef, 60));
// row #5
Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53));
Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 46), ref Unsafe.Add(ref elemRef, 53));
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 47), ref Unsafe.Add(ref elemRef, 61));
// row #6
Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62));
static void Swap(ref float a, ref float b)
{
float tmp = a;
a = b;
b = tmp;
}
RuntimeUtility.Swap(ref Unsafe.Add(ref elemRef, 55), ref Unsafe.Add(ref elemRef, 62));
}
[MethodImpl(InliningOptions.ShortMethod)]

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.CmykAvx.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -96,4 +95,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
#endif

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.GrayScaleAvx.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -69,4 +68,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
#endif

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.RgbAvx.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -53,4 +52,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
#endif

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YCbCrAvx.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -122,4 +121,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
#endif

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverter.YccKAvx.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -133,4 +132,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
#endif

2
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterAvx.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
@ -34,4 +33,3 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
#endif

14
src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs

@ -20,6 +20,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Initializes a new instance of the <see cref="JpegColorConverterBase"/> class.
/// </summary>
/// <param name="colorSpace">The color space.</param>
/// <param name="precision">The precision in bits.</param>
protected JpegColorConverterBase(JpegColorSpace colorSpace, int precision)
{
this.ColorSpace = colorSpace;
@ -66,6 +68,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Returns the <see cref="JpegColorConverterBase"/> corresponding to the given <see cref="JpegColorSpace"/>
/// </summary>
/// <param name="colorSpace">The color space.</param>
/// <param name="precision">The precision in bits.</param>
/// <exception cref="InvalidImageContentException">Invalid colorspace.</exception>
public static JpegColorConverterBase GetConverter(JpegColorSpace colorSpace, int precision)
{
JpegColorConverterBase converter = Array.Find(
@ -75,7 +80,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
if (converter is null)
{
throw new Exception($"Could not find any converter for JpegColorSpace {colorSpace}!");
throw new InvalidImageContentException($"Could not find any converter for JpegColorSpace {colorSpace}!");
}
return converter;
@ -104,7 +109,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
// 5 color types with 2 supported precisions: 8 bit & 12 bit
const int colorConvertersCount = 5 * 2;
var converters = new JpegColorConverterBase[colorConvertersCount];
JpegColorConverterBase[] converters = new JpegColorConverterBase[colorConvertersCount];
// 8-bit converters
converters[0] = GetYCbCrConverter(8);
@ -126,6 +131,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Returns the <see cref="JpegColorConverterBase"/>s for the YCbCr colorspace.
/// </summary>
/// <param name="precision">The precision in bits.</param>
private static JpegColorConverterBase GetYCbCrConverter(int precision)
{
if (JpegColorConverterAvx.IsSupported)
@ -144,6 +150,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Returns the <see cref="JpegColorConverterBase"/>s for the YccK colorspace.
/// </summary>
/// <param name="precision">The precision in bits.</param>
private static JpegColorConverterBase GetYccKConverter(int precision)
{
if (JpegColorConverterAvx.IsSupported)
@ -162,6 +169,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Returns the <see cref="JpegColorConverterBase"/>s for the CMYK colorspace.
/// </summary>
/// <param name="precision">The precision in bits.</param>
private static JpegColorConverterBase GetCmykConverter(int precision)
{
if (JpegColorConverterAvx.IsSupported)
@ -180,6 +188,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Returns the <see cref="JpegColorConverterBase"/>s for the gray scale colorspace.
/// </summary>
/// <param name="precision">The precision in bits.</param>
private static JpegColorConverterBase GetGrayScaleConverter(int precision)
{
if (JpegColorConverterAvx.IsSupported)
@ -198,6 +207,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Returns the <see cref="JpegColorConverterBase"/>s for the RGB colorspace.
/// </summary>
/// <param name="precision">The precision in bits.</param>
private static JpegColorConverterBase GetRgbConverter(int precision)
{
if (JpegColorConverterAvx.IsSupported)

25
src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs

@ -225,10 +225,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
for (int i = 0; i < this.components.Length; i++)
{
var component = this.components[i] as ArithmeticDecodingComponent;
this.dcDecodingTables[i] = this.GetArithmeticTable(arithmeticDecodingTables, true, component.DcTableId);
ArithmeticDecodingComponent component = this.components[i] as ArithmeticDecodingComponent;
this.dcDecodingTables[i] = GetArithmeticTable(arithmeticDecodingTables, true, component.DcTableId);
component.DcStatistics = this.CreateOrGetStatisticsBin(true, component.DcTableId);
this.acDecodingTables[i] = this.GetArithmeticTable(arithmeticDecodingTables, false, component.AcTableId);
this.acDecodingTables[i] = GetArithmeticTable(arithmeticDecodingTables, false, component.AcTableId);
component.AcStatistics = this.CreateOrGetStatisticsBin(false, component.AcTableId);
}
}
@ -276,7 +276,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.spectralConverter.InjectFrameData(frame, jpegData);
}
private ArithmeticDecodingTable GetArithmeticTable(List<ArithmeticDecodingTable> arithmeticDecodingTables, bool isDcTable, int identifier)
private static ArithmeticDecodingTable GetArithmeticTable(List<ArithmeticDecodingTable> arithmeticDecodingTables, bool isDcTable, int identifier)
{
int tableClass = isDcTable ? 0 : 1;
@ -306,15 +306,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
}
}
var statistic = new ArithmeticStatistics(dc, identifier);
ArithmeticStatistics statistic = new(dc, identifier);
this.statistics.Add(statistic);
return statistic;
}
private void ParseBaselineData()
{
foreach (ArithmeticDecodingComponent component in this.components)
for (int i = 0; i < this.components.Length; i++)
{
ArithmeticDecodingComponent component = (ArithmeticDecodingComponent)this.components[i];
component.DcPredictor = 0;
component.DcContext = 0;
component.DcStatistics?.Reset();
@ -441,7 +442,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
for (int k = 0; k < this.scanComponentCount; k++)
{
int order = this.frame.ComponentOrder[k];
var component = this.components[order] as ArithmeticDecodingComponent;
ArithmeticDecodingComponent component = this.components[order] as ArithmeticDecodingComponent;
ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId];
ref ArithmeticDecodingTable acDecodingTable = ref this.acDecodingTables[component.AcTableId];
@ -491,7 +492,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void ParseBaselineDataSingleComponent()
{
var component = this.frame.Components[0] as ArithmeticDecodingComponent;
ArithmeticDecodingComponent component = this.frame.Components[0] as ArithmeticDecodingComponent;
int mcuLines = this.frame.McusPerColumn;
int w = component.WidthInBlocks;
int h = component.SamplingFactors.Height;
@ -537,7 +538,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void ParseBaselineDataNonInterleaved()
{
var component = (ArithmeticDecodingComponent)this.components[this.frame.ComponentOrder[0]];
ArithmeticDecodingComponent component = (ArithmeticDecodingComponent)this.components[this.frame.ComponentOrder[0]];
ref JpegBitReader reader = ref this.scanBuffer;
int w = component.WidthInBlocks;
@ -586,7 +587,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
for (int k = 0; k < this.scanComponentCount; k++)
{
int order = this.frame.ComponentOrder[k];
var component = this.components[order] as ArithmeticDecodingComponent;
ArithmeticDecodingComponent component = this.components[order] as ArithmeticDecodingComponent;
ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId];
int h = component.HorizontalSamplingFactor;
@ -628,7 +629,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
private void ParseProgressiveDataNonInterleaved()
{
var component = this.components[this.frame.ComponentOrder[0]] as ArithmeticDecodingComponent;
ArithmeticDecodingComponent component = this.components[this.frame.ComponentOrder[0]] as ArithmeticDecodingComponent;
ref JpegBitReader reader = ref this.scanBuffer;
int w = component.WidthInBlocks;
@ -1140,7 +1141,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
for (int i = 0; i < this.components.Length; i++)
{
var component = this.components[i] as ArithmeticDecodingComponent;
ArithmeticDecodingComponent component = this.components[i] as ArithmeticDecodingComponent;
component.DcPredictor = 0;
}

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

Loading…
Cancel
Save