diff --git a/.gitattributes b/.gitattributes
index 70ced69033..355b64dce1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -87,7 +87,6 @@
*.eot binary
*.exe binary
*.otf binary
-*.pbm binary
*.pdf binary
*.ppt binary
*.pptx binary
@@ -95,7 +94,6 @@
*.snk binary
*.ttc binary
*.ttf binary
-*.wbmp binary
*.woff binary
*.woff2 binary
*.xls binary
@@ -126,3 +124,9 @@
*.dds filter=lfs diff=lfs merge=lfs -text
*.ktx filter=lfs diff=lfs merge=lfs -text
*.ktx2 filter=lfs diff=lfs merge=lfs -text
+*.pam filter=lfs diff=lfs merge=lfs -text
+*.pbm filter=lfs diff=lfs merge=lfs -text
+*.pgm filter=lfs diff=lfs merge=lfs -text
+*.ppm filter=lfs diff=lfs merge=lfs -text
+*.pnm filter=lfs diff=lfs merge=lfs -text
+*.wbmp filter=lfs diff=lfs merge=lfs -text
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 1326c72e86..62a8bf2b4f 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,8 +1,5 @@
blank_issues_enabled: false
contact_links:
- - name: Ask a Question
- url: https://github.com/SixLabors/ImageSharp/discussions?discussions_q=category%3AQ%26A
- about: Ask a question about this project.
- name: Feature Request
url: https://github.com/SixLabors/ImageSharp/discussions?discussions_q=category%3AIdeas
about: Share ideas for new features for this project.
diff --git a/.github/ISSUE_TEMPLATE/oss-bug-report.md b/.github/ISSUE_TEMPLATE/oss-bug-report.md
index e0d37de538..9e9567a99a 100644
--- a/.github/ISSUE_TEMPLATE/oss-bug-report.md
+++ b/.github/ISSUE_TEMPLATE/oss-bug-report.md
@@ -1,6 +1,6 @@
---
name: "OSS : Bug Report"
-about: Create a report to help us improve the project.
+about: Create a report to help us improve the project. OSS Issues are not guaranteed to be triaged.
labels: needs triage
---
diff --git a/Directory.Build.props b/Directory.Build.props
index 3899ce939f..26b3cc5afc 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -13,6 +13,9 @@
$(MSBuildThisFileDirectory)
+
+
+ $(DefineConstants);DEBUG
@@ -30,5 +33,4 @@
true
-
diff --git a/README.md b/README.md
index ab16bbb76a..fdf14b4963 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ ImageSharp is a new, fully featured, fully managed, cross-platform, 2D graphics
ImageSharp is designed from the ground up to be flexible and extensible. The library provides API endpoints for common image processing operations and the building blocks to allow for the development of additional operations.
-Built against [.NET Standard 1.3](https://docs.microsoft.com/en-us/dotnet/standard/net-standard), ImageSharp can be used in device, cloud, and embedded/IoT scenarios.
+Built against [.NET Standard 2.0](https://docs.microsoft.com/en-us/dotnet/standard/net-standard), ImageSharp can be used in device, cloud, and embedded/IoT scenarios.
## License
diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
index 54a773be05..829c6155db 100644
--- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
+++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
@@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Advanced
/// The source.
/// The row.
/// The
- public static Memory GetPixelRowMemory(this ImageFrame source, int rowIndex)
+ public static Memory DangerousGetPixelRowMemory(this ImageFrame source, int rowIndex)
where TPixel : unmanaged, IPixel
{
Guard.NotNull(source, nameof(source));
@@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.Advanced
/// The source.
/// The row.
/// The
- public static Memory GetPixelRowMemory(this Image source, int rowIndex)
+ public static Memory DangerousGetPixelRowMemory(this Image source, int rowIndex)
where TPixel : unmanaged, IPixel
{
Guard.NotNull(source, nameof(source));
diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs
index 3961cc6c57..82a146dc72 100644
--- a/src/ImageSharp/Advanced/AotCompilerTools.cs
+++ b/src/ImageSharp/Advanced/AotCompilerTools.cs
@@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
+using SixLabors.ImageSharp.Formats.Pbm;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Tiff;
@@ -74,6 +75,7 @@ namespace SixLabors.ImageSharp.Advanced
Seed();
Seed();
+ Seed();
Seed();
Seed();
Seed();
@@ -148,6 +150,7 @@ namespace SixLabors.ImageSharp.Advanced
Image img = default;
img.CloneAs(default);
img.CloneAs(default);
+ img.CloneAs(default);
img.CloneAs(default);
img.CloneAs(default);
img.CloneAs(default);
@@ -200,6 +203,7 @@ namespace SixLabors.ImageSharp.Advanced
default(BmpEncoderCore).Encode(default, default, default);
default(GifEncoderCore).Encode(default, default, default);
default(JpegEncoderCore).Encode(default, default, default);
+ default(PbmEncoderCore).Encode(default, default, default);
default(PngEncoderCore).Encode(default, default, default);
default(TgaEncoderCore).Encode(default, default, default);
default(TiffEncoderCore).Encode(default, default, default);
@@ -217,6 +221,7 @@ namespace SixLabors.ImageSharp.Advanced
default(BmpDecoderCore).Decode(default, default, default);
default(GifDecoderCore).Decode(default, default, default);
default(JpegDecoderCore).Decode(default, default, default);
+ default(PbmDecoderCore).Decode(default, default, default);
default(PngDecoderCore).Decode(default, default, default);
default(TgaDecoderCore).Decode(default, default, default);
default(TiffDecoderCore).Decode(default, default, default);
@@ -234,6 +239,7 @@ namespace SixLabors.ImageSharp.Advanced
AotCompileImageEncoder();
AotCompileImageEncoder();
AotCompileImageEncoder();
+ AotCompileImageEncoder();
AotCompileImageEncoder();
AotCompileImageEncoder();
AotCompileImageEncoder();
@@ -251,6 +257,7 @@ namespace SixLabors.ImageSharp.Advanced
AotCompileImageDecoder();
AotCompileImageDecoder();
AotCompileImageDecoder();
+ AotCompileImageDecoder();
AotCompileImageDecoder();
AotCompileImageDecoder();
AotCompileImageDecoder();
@@ -529,7 +536,7 @@ namespace SixLabors.ImageSharp.Advanced
private static void AotCompileMemoryManagers()
where TPixel : unmanaged, IPixel
{
- AotCompileMemoryManager();
+ AotCompileMemoryManager();
AotCompileMemoryManager();
}
diff --git a/src/ImageSharp/Color/Color.Conversions.cs b/src/ImageSharp/Color/Color.Conversions.cs
index bf7869e53d..5c10bfaa09 100644
--- a/src/ImageSharp/Color/Color.Conversions.cs
+++ b/src/ImageSharp/Color/Color.Conversions.cs
@@ -89,6 +89,17 @@ namespace SixLabors.ImageSharp
this.boxedHighPrecisionPixel = null;
}
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The containing the color information.
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Color(Abgr32 pixel)
+ {
+ this.data = new Rgba64(pixel);
+ this.boxedHighPrecisionPixel = null;
+ }
+
///
/// Initializes a new instance of the struct.
///
@@ -177,6 +188,19 @@ namespace SixLabors.ImageSharp
return value;
}
+ [MethodImpl(InliningOptions.ShortMethod)]
+ internal Abgr32 ToAbgr32()
+ {
+ if (this.boxedHighPrecisionPixel is null)
+ {
+ return this.data.ToAbgr32();
+ }
+
+ Abgr32 value = default;
+ value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4());
+ return value;
+ }
+
[MethodImpl(InliningOptions.ShortMethod)]
internal Rgb24 ToRgb24()
{
diff --git a/src/ImageSharp/Common/Helpers/DebugGuard.cs b/src/ImageSharp/Common/Helpers/DebugGuard.cs
index f56cb37a81..f438ca9e24 100644
--- a/src/ImageSharp/Common/Helpers/DebugGuard.cs
+++ b/src/ImageSharp/Common/Helpers/DebugGuard.cs
@@ -26,6 +26,20 @@ namespace SixLabors
}
}
+ ///
+ /// Verifies whether a condition (indicating disposed state) is met, throwing an ObjectDisposedException if it's true.
+ ///
+ /// Whether the object is disposed.
+ /// The name of the object.
+ [Conditional("DEBUG")]
+ public static void NotDisposed(bool isDisposed, string objectName)
+ {
+ if (isDisposed)
+ {
+ throw new ObjectDisposedException(objectName);
+ }
+ }
+
///
/// Verifies, that the target span is of same size than the 'other' span.
///
diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs
index 0b5cc21cb8..0f6efcb3c4 100644
--- a/src/ImageSharp/Common/Helpers/Guard.cs
+++ b/src/ImageSharp/Common/Helpers/Guard.cs
@@ -2,9 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-#if NETSTANDARD1_3
-using System.Reflection;
-#endif
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp;
@@ -22,11 +19,7 @@ namespace SixLabors
[MethodImpl(InliningOptions.ShortMethod)]
public static void MustBeValueType(TValue value, string parameterName)
{
- if (value.GetType()
-#if NETSTANDARD1_3
- .GetTypeInfo()
-#endif
- .IsValueType)
+ if (value.GetType().IsValueType)
{
return;
}
diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs
index fa0af823d5..7de838bc94 100644
--- a/src/ImageSharp/Common/Helpers/Numerics.cs
+++ b/src/ImageSharp/Common/Helpers/Numerics.cs
@@ -907,5 +907,71 @@ namespace SixLabors.ImageSharp
/// Divisor value.
/// Ceiled division result.
public static uint DivideCeil(uint value, uint divisor) => (value + divisor - 1) / divisor;
+
+ ///
+ /// Rotates the specified value left by the specified number of bits.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate with.
+ /// The rotated value.
+ [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
+ ///
+ /// Rotates the specified value left by the specified number of bits.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate with.
+ /// The rotated value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint RotateLeftSoftwareFallback(uint value, int offset)
+ => (value << offset) | (value >> (32 - offset));
+#endif
+
+ ///
+ /// Rotates the specified value right by the specified number of bits.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate with.
+ /// The rotated value.
+ [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
+ ///
+ /// Rotates the specified value right by the specified number of bits.
+ ///
+ /// The value to rotate.
+ /// The number of bits to rotate with.
+ /// The rotated value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint RotateRightSoftwareFallback(uint value, int offset)
+ => (value >> offset) | (value << (32 - offset));
+#endif
+
+ ///
+ /// Tells whether input value is outside of the given range.
+ ///
+ /// Value.
+ /// Mininum value, inclusive.
+ /// Maximum value, inclusive.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsOutOfRange(int value, int min, int max)
+ => (uint)(value - min) > (uint)(max - min);
}
}
diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
index 7687a5b95f..049c611851 100644
--- a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
+++ b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
@@ -28,6 +28,10 @@ namespace SixLabors.ImageSharp
///
/// The source span of bytes.
/// The destination span of bytes.
+ ///
+ /// Implementation can assume that source.Length is less or equal than dest.Length.
+ /// Loops should iterate using source.Length.
+ ///
void RunFallbackShuffle(ReadOnlySpan source, Span dest);
}
@@ -153,7 +157,7 @@ namespace SixLabors.ImageSharp
// packed = [W Z Y X]
// ROTR(8, packedArgb) = [Y Z W X]
- Unsafe.Add(ref dBase, i) = (packed >> 8) | (packed << 24);
+ Unsafe.Add(ref dBase, i) = Numerics.RotateRight(packed, 8);
}
}
}
@@ -184,7 +188,40 @@ namespace SixLabors.ImageSharp
// tmp1 + tmp3 = [W X Y Z]
uint tmp1 = packed & 0xFF00FF00;
uint tmp2 = packed & 0x00FF00FF;
- uint tmp3 = (tmp2 << 16) | (tmp2 >> 16);
+ uint tmp3 = Numerics.RotateLeft(tmp2, 16);
+
+ Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
+ }
+ }
+ }
+
+ internal readonly struct XWZYShuffle4 : IShuffle4
+ {
+ public byte Control
+ {
+ [MethodImpl(InliningOptions.ShortMethod)]
+ get => SimdUtils.Shuffle.MmShuffle(1, 2, 3, 0);
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void RunFallbackShuffle(ReadOnlySpan source, Span dest)
+ {
+ ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source));
+ ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
+ int n = source.Length / 4;
+
+ for (int i = 0; i < n; i++)
+ {
+ uint packed = Unsafe.Add(ref sBase, i);
+
+ // packed = [W Z Y X]
+ // tmp1 = [0 Z 0 X]
+ // tmp2 = [W 0 Y 0]
+ // tmp3=ROTL(16, tmp2) = [Y 0 W 0]
+ // tmp1 + tmp3 = [Y Z W X]
+ uint tmp1 = packed & 0x00FF00FF;
+ uint tmp2 = packed & 0xFF00FF00;
+ uint tmp3 = Numerics.RotateLeft(tmp2, 16);
Unsafe.Add(ref dBase, i) = tmp1 + tmp3;
}
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs b/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs
index 07744566a3..abf9e9fed0 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs
@@ -77,6 +77,7 @@ namespace SixLabors.ImageSharp
TShuffle shuffle)
where TShuffle : struct, IShuffle3
{
+ // Source length should be smaller than dest length, and divisible by 3.
VerifyShuffle3SpanInput(source, dest);
#if SUPPORTS_RUNTIME_INTRINSICS
@@ -182,9 +183,9 @@ namespace SixLabors.ImageSharp
where T : struct
{
DebugGuard.IsTrue(
- source.Length == dest.Length,
+ source.Length <= dest.Length,
nameof(source),
- "Input spans must be of same length!");
+ "Source should fit into dest!");
DebugGuard.IsTrue(
source.Length % 3 == 0,
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs
index 6d82cfad01..29068a82c9 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs
@@ -33,18 +33,6 @@ namespace SixLabors.ImageSharp
public static bool HasVector4 { get; } =
Vector.IsHardwareAccelerated && Vector.Count == 4;
- public static bool HasAvx2
- {
- get
- {
-#if SUPPORTS_RUNTIME_INTRINSICS
- return Avx2.IsSupported;
-#else
- return false;
-#endif
- }
- }
-
///
/// Transform all scalars in 'v' in a way that converting them to would have rounding semantics.
///
diff --git a/src/ImageSharp/Common/Tuples/Vector4Pair.cs b/src/ImageSharp/Common/Tuples/Vector4Pair.cs
deleted file mode 100644
index 6294a61775..0000000000
--- a/src/ImageSharp/Common/Tuples/Vector4Pair.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace SixLabors.ImageSharp.Tuples
-{
- ///
- /// Its faster to process multiple Vector4-s together, so let's pair them!
- /// On AVX2 this pair should be convertible to of !
- /// TODO: Investigate defining this as union with an Octet.OfSingle type.
- ///
- [StructLayout(LayoutKind.Sequential)]
- internal struct Vector4Pair
- {
- public Vector4 A;
-
- public Vector4 B;
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void MultiplyInplace(float value)
- {
- this.A *= value;
- this.B *= value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void AddInplace(Vector4 value)
- {
- this.A += value;
- this.B += value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void AddInplace(ref Vector4Pair other)
- {
- this.A += other.A;
- this.B += other.B;
- }
-
- /// .
- /// Downscale method, specific to Jpeg color conversion. Works only if Vector{float}.Count == 4! /// TODO: Move it somewhere else.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void RoundAndDownscalePreVector8(float downscaleFactor)
- {
- ref Vector a = ref Unsafe.As>(ref this.A);
- a = a.FastRound();
-
- ref Vector b = ref Unsafe.As>(ref this.B);
- b = b.FastRound();
-
- // Downscale by 1/factor
- var scale = new Vector4(1 / downscaleFactor);
- this.A *= scale;
- this.B *= scale;
- }
-
- ///
- /// AVX2-only Downscale method, specific to Jpeg color conversion.
- /// TODO: Move it somewhere else.
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void RoundAndDownscaleVector8(float downscaleFactor)
- {
- ref Vector self = ref Unsafe.As>(ref this);
- Vector v = self;
- v = v.FastRound();
-
- // Downscale by 1/factor
- v *= new Vector(1 / downscaleFactor);
- self = v;
- }
-
- public override string ToString()
- {
- return $"{nameof(Vector4Pair)}({this.A}, {this.B})";
- }
- }
-}
diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs
index ea9524827f..ca83b0764e 100644
--- a/src/ImageSharp/Configuration.cs
+++ b/src/ImageSharp/Configuration.cs
@@ -8,6 +8,7 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
+using SixLabors.ImageSharp.Formats.Pbm;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Tiff;
@@ -26,10 +27,11 @@ namespace SixLabors.ImageSharp
///
/// A lazily initialized configuration default instance.
///
- private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance);
+ private static readonly Lazy Lazy = new(CreateDefaultInstance);
private const int DefaultStreamProcessingBufferSize = 8096;
private int streamProcessingBufferSize = DefaultStreamProcessingBufferSize;
private int maxDegreeOfParallelism = Environment.ProcessorCount;
+ private MemoryAllocator memoryAllocator = MemoryAllocator.Default;
///
/// Initializes a new instance of the class.
@@ -95,6 +97,14 @@ namespace SixLabors.ImageSharp
}
}
+ ///
+ /// Gets or sets a value indicating whether to force image buffers to be contiguous whenever possible.
+ ///
+ ///
+ /// Contiguous allocations are not possible, if the image needs a buffer larger than .
+ ///
+ public bool PreferContiguousImageBuffers { get; set; }
+
///
/// Gets a set of properties for the Configuration.
///
@@ -117,9 +127,31 @@ namespace SixLabors.ImageSharp
public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager();
///
- /// Gets or sets the that is currently in use.
+ /// Gets or sets the that is currently in use.
+ /// Defaults to .
+ ///
+ /// Allocators are expensive, so it is strongly recommended to use only one busy instance per process.
+ /// In case you need to customize it, you can ensure this by changing
///
- public MemoryAllocator MemoryAllocator { get; set; } = ArrayPoolMemoryAllocator.CreateDefault();
+ ///
+ /// It's possible to reduce allocator footprint by assigning a custom instance created with
+ /// , but note that since the default pooling
+ /// allocators are expensive, it is strictly recommended to use a single process-wide allocator.
+ /// You can ensure this by altering the allocator of , or by implementing custom application logic that
+ /// manages allocator lifetime.
+ ///
+ /// If an allocator has to be dropped for some reason,
+ /// shall be invoked after disposing all associated instances.
+ ///
+ public MemoryAllocator MemoryAllocator
+ {
+ get => this.memoryAllocator;
+ set
+ {
+ Guard.NotNull(value, nameof(this.MemoryAllocator));
+ this.memoryAllocator = value;
+ }
+ }
///
/// Gets the maximum header size of all the formats.
@@ -165,7 +197,7 @@ namespace SixLabors.ImageSharp
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
StreamProcessingBufferSize = this.StreamProcessingBufferSize,
ImageFormatsManager = this.ImageFormatsManager,
- MemoryAllocator = this.MemoryAllocator,
+ memoryAllocator = this.memoryAllocator,
ImageOperationsProvider = this.ImageOperationsProvider,
ReadOrigin = this.ReadOrigin,
FileSystem = this.FileSystem,
@@ -178,6 +210,7 @@ namespace SixLabors.ImageSharp
///
///
/// .
+ /// .
/// .
/// .
/// .
@@ -188,6 +221,7 @@ namespace SixLabors.ImageSharp
new JpegConfigurationModule(),
new GifConfigurationModule(),
new BmpConfigurationModule(),
+ new PbmConfigurationModule(),
new TgaConfigurationModule(),
new TiffConfigurationModule(),
new WebpConfigurationModule());
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 8919befcb2..41adc1cfff 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -306,7 +306,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int newY = Invert(y, height, inverted);
int rowStartIdx = y * width;
Span bufferRow = bufferSpan.Slice(rowStartIdx, width);
- Span pixelRow = pixels.GetRowSpan(newY);
+ Span pixelRow = pixels.DangerousGetRowSpan(newY);
bool rowHasUndefinedPixels = rowsWithUndefinedPixelsSpan[y];
if (rowHasUndefinedPixels)
@@ -377,7 +377,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
for (int y = 0; y < height; y++)
{
int newY = Invert(y, height, inverted);
- Span pixelRow = pixels.GetRowSpan(newY);
+ Span pixelRow = pixels.DangerousGetRowSpan(newY);
bool rowHasUndefinedPixels = rowsWithUndefinedPixelsSpan[y];
if (rowHasUndefinedPixels)
{
@@ -826,7 +826,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int newY = Invert(y, height, inverted);
this.stream.Read(rowSpan);
int offset = 0;
- Span pixelRow = pixels.GetRowSpan(newY);
+ Span pixelRow = pixels.DangerousGetRowSpan(newY);
for (int x = 0; x < arrayWidth; x++)
{
@@ -878,7 +878,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
this.stream.Read(bufferSpan);
int newY = Invert(y, height, inverted);
- Span pixelRow = pixels.GetRowSpan(newY);
+ Span pixelRow = pixels.DangerousGetRowSpan(newY);
int offset = 0;
for (int x = 0; x < width; x++)
@@ -933,7 +933,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
this.stream.Read(rowSpan);
int newY = Invert(y, height, inverted);
- Span pixelSpan = pixels.GetRowSpan(newY);
+ Span pixelSpan = pixels.DangerousGetRowSpan(newY);
PixelOperations.Instance.FromBgr24Bytes(
this.Configuration,
rowSpan,
@@ -961,7 +961,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
this.stream.Read(rowSpan);
int newY = Invert(y, height, inverted);
- Span pixelSpan = pixels.GetRowSpan(newY);
+ Span pixelSpan = pixels.DangerousGetRowSpan(newY);
PixelOperations.Instance.FromBgra32Bytes(
this.Configuration,
rowSpan,
@@ -1031,7 +1031,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.stream.Read(rowSpan);
int newY = Invert(y, height, inverted);
- Span pixelSpan = pixels.GetRowSpan(newY);
+ Span pixelSpan = pixels.DangerousGetRowSpan(newY);
PixelOperations.Instance.FromBgra32Bytes(
this.Configuration,
@@ -1054,7 +1054,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
width);
int newY = Invert(y, height, inverted);
- Span pixelSpan = pixels.GetRowSpan(newY);
+ Span pixelSpan = pixels.DangerousGetRowSpan(newY);
for (int x = 0; x < width; x++)
{
@@ -1109,7 +1109,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
this.stream.Read(bufferSpan);
int newY = Invert(y, height, inverted);
- Span pixelRow = pixels.GetRowSpan(newY);
+ Span pixelRow = pixels.DangerousGetRowSpan(newY);
int offset = 0;
for (int x = 0; x < width; x++)
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index c6ca5b09d2..6384074df3 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -274,7 +274,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
for (int y = pixels.Height - 1; y >= 0; y--)
{
- Span pixelSpan = pixels.GetRowSpan(y);
+ Span pixelSpan = pixels.DangerousGetRowSpan(y);
PixelOperations.Instance.ToBgra32Bytes(
this.configuration,
pixelSpan,
@@ -300,7 +300,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
for (int y = pixels.Height - 1; y >= 0; y--)
{
- Span pixelSpan = pixels.GetRowSpan(y);
+ Span pixelSpan = pixels.DangerousGetRowSpan(y);
PixelOperations.Instance.ToBgr24Bytes(
this.configuration,
pixelSpan,
@@ -326,7 +326,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
for (int y = pixels.Height - 1; y >= 0; y--)
{
- Span pixelSpan = pixels.GetRowSpan(y);
+ Span pixelSpan = pixels.DangerousGetRowSpan(y);
PixelOperations.Instance.ToBgra5551Bytes(
this.configuration,
@@ -379,7 +379,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
for (int y = image.Height - 1; y >= 0; y--)
{
- ReadOnlySpan pixelSpan = quantized.GetPixelRowSpan(y);
+ ReadOnlySpan pixelSpan = quantized.DangerousGetRowSpan(y);
stream.Write(pixelSpan);
for (int i = 0; i < this.padding; i++)
@@ -413,10 +413,10 @@ namespace SixLabors.ImageSharp.Formats.Bmp
}
stream.Write(colorPalette);
-
+ Buffer2D imageBuffer = image.PixelBuffer;
for (int y = image.Height - 1; y >= 0; y--)
{
- ReadOnlySpan inputPixelRow = image.GetPixelRowSpan(y);
+ ReadOnlySpan inputPixelRow = imageBuffer.DangerousGetRowSpan(y);
ReadOnlySpan outputPixelRow = MemoryMarshal.AsBytes(inputPixelRow);
stream.Write(outputPixelRow);
@@ -447,11 +447,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
ReadOnlySpan quantizedColorPalette = quantized.Palette.Span;
this.WriteColorPalette(stream, quantizedColorPalette, colorPalette);
- ReadOnlySpan pixelRowSpan = quantized.GetPixelRowSpan(0);
+ ReadOnlySpan pixelRowSpan = quantized.DangerousGetRowSpan(0);
int rowPadding = pixelRowSpan.Length % 2 != 0 ? this.padding - 1 : this.padding;
for (int y = image.Height - 1; y >= 0; y--)
{
- pixelRowSpan = quantized.GetPixelRowSpan(y);
+ pixelRowSpan = quantized.DangerousGetRowSpan(y);
int endIdx = pixelRowSpan.Length % 2 == 0 ? pixelRowSpan.Length : pixelRowSpan.Length - 1;
for (int i = 0; i < endIdx; i += 2)
@@ -491,11 +491,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
ReadOnlySpan quantizedColorPalette = quantized.Palette.Span;
this.WriteColorPalette(stream, quantizedColorPalette, colorPalette);
- ReadOnlySpan quantizedPixelRow = quantized.GetPixelRowSpan(0);
+ ReadOnlySpan quantizedPixelRow = quantized.DangerousGetRowSpan(0);
int rowPadding = quantizedPixelRow.Length % 8 != 0 ? this.padding - 1 : this.padding;
for (int y = image.Height - 1; y >= 0; y--)
{
- quantizedPixelRow = quantized.GetPixelRowSpan(y);
+ quantizedPixelRow = quantized.DangerousGetRowSpan(y);
int endIdx = quantizedPixelRow.Length % 8 == 0 ? quantizedPixelRow.Length : quantizedPixelRow.Length - 8;
for (int i = 0; i < endIdx; i += 8)
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 482a761530..3e33a6e379 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -445,7 +445,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
for (int y = descriptorTop; y < descriptorBottom && y < imageHeight; y++)
{
- ref byte indicesRowRef = ref MemoryMarshal.GetReference(indices.GetRowSpan(y - descriptorTop));
+ ref byte indicesRowRef = ref MemoryMarshal.GetReference(indices.DangerousGetRowSpan(y - descriptorTop));
// Check if this image is interlaced.
int writeY; // the target y offset to write to
@@ -481,7 +481,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
writeY = y;
}
- ref TPixel rowRef = ref MemoryMarshal.GetReference(imageFrame.GetPixelRowSpan(writeY));
+ ref TPixel rowRef = ref MemoryMarshal.GetReference(imageFrame.PixelBuffer.DangerousGetRowSpan(writeY));
if (!transFlag)
{
diff --git a/src/ImageSharp/Formats/Gif/LzwDecoder.cs b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
index 9eaa55566b..68227db53d 100644
--- a/src/ImageSharp/Formats/Gif/LzwDecoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwDecoder.cs
@@ -115,14 +115,14 @@ namespace SixLabors.ImageSharp.Formats.Gif
int y = 0;
int x = 0;
int rowMax = width;
- ref byte pixelsRowRef = ref MemoryMarshal.GetReference(pixels.GetRowSpan(y));
+ ref byte pixelsRowRef = ref MemoryMarshal.GetReference(pixels.DangerousGetRowSpan(y));
while (xyz < length)
{
// Reset row reference.
if (xyz == rowMax)
{
x = 0;
- pixelsRowRef = ref MemoryMarshal.GetReference(pixels.GetRowSpan(++y));
+ pixelsRowRef = ref MemoryMarshal.GetReference(pixels.DangerousGetRowSpan(++y));
rowMax = (y * width) + width;
}
diff --git a/src/ImageSharp/Formats/Gif/LzwEncoder.cs b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
index e9fb7ab00b..c52e34f963 100644
--- a/src/ImageSharp/Formats/Gif/LzwEncoder.cs
+++ b/src/ImageSharp/Formats/Gif/LzwEncoder.cs
@@ -275,7 +275,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
for (int y = 0; y < indexedPixels.Height; y++)
{
- ref byte rowSpanRef = ref MemoryMarshal.GetReference(indexedPixels.GetRowSpan(y));
+ ref byte rowSpanRef = ref MemoryMarshal.GetReference(indexedPixels.DangerousGetRowSpan(y));
int offsetX = y == 0 ? 1 : 0;
for (int x = offsetX; x < indexedPixels.Width; x++)
diff --git a/src/ImageSharp/Formats/ImageExtensions.Save.cs b/src/ImageSharp/Formats/ImageExtensions.Save.cs
index c5237f2bc7..a6a65aef62 100644
--- a/src/ImageSharp/Formats/ImageExtensions.Save.cs
+++ b/src/ImageSharp/Formats/ImageExtensions.Save.cs
@@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
+using SixLabors.ImageSharp.Formats.Pbm;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Webp;
@@ -331,6 +332,109 @@ namespace SixLabors.ImageSharp
encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(JpegFormat.Instance),
cancellationToken);
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// Thrown if the path is null.
+ public static void SaveAsPbm(this Image source, string path) => SaveAsPbm(source, path, null);
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// Thrown if the path is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsPbmAsync(this Image source, string path) => SaveAsPbmAsync(source, path, null);
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// The token to monitor for cancellation requests.
+ /// Thrown if the path is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsPbmAsync(this Image source, string path, CancellationToken cancellationToken)
+ => SaveAsPbmAsync(source, path, null, cancellationToken);
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// The encoder to save the image with.
+ /// Thrown if the path is null.
+ public static void SaveAsPbm(this Image source, string path, PbmEncoder encoder) =>
+ source.Save(
+ path,
+ encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance));
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The file path to save the image to.
+ /// The encoder to save the image with.
+ /// The token to monitor for cancellation requests.
+ /// Thrown if the path is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsPbmAsync(this Image source, string path, PbmEncoder encoder, CancellationToken cancellationToken = default) =>
+ source.SaveAsync(
+ path,
+ encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance),
+ cancellationToken);
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// Thrown if the stream is null.
+ public static void SaveAsPbm(this Image source, Stream stream)
+ => SaveAsPbm(source, stream, null);
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// The token to monitor for cancellation requests.
+ /// Thrown if the stream is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsPbmAsync(this Image source, Stream stream, CancellationToken cancellationToken = default)
+ => SaveAsPbmAsync(source, stream, null, cancellationToken);
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// The encoder to save the image with.
+ /// Thrown if the stream is null.
+ /// A representing the asynchronous operation.
+ public static void SaveAsPbm(this Image source, Stream stream, PbmEncoder encoder)
+ => source.Save(
+ stream,
+ encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance));
+
+ ///
+ /// Saves the image to the given stream with the Pbm format.
+ ///
+ /// The image this method extends.
+ /// The stream to save the image to.
+ /// The encoder to save the image with.
+ /// The token to monitor for cancellation requests.
+ /// Thrown if the stream is null.
+ /// A representing the asynchronous operation.
+ public static Task SaveAsPbmAsync(this Image source, Stream stream, PbmEncoder encoder, CancellationToken cancellationToken = default) =>
+ source.SaveAsync(
+ stream,
+ encoder ?? source.GetConfiguration().ImageFormatsManager.FindEncoder(PbmFormat.Instance),
+ cancellationToken);
+
///
/// Saves the image to the given stream with the Png format.
///
diff --git a/src/ImageSharp/Formats/ImageExtensions.Save.tt b/src/ImageSharp/Formats/ImageExtensions.Save.tt
index 874f3ab0dc..c4a00b37cb 100644
--- a/src/ImageSharp/Formats/ImageExtensions.Save.tt
+++ b/src/ImageSharp/Formats/ImageExtensions.Save.tt
@@ -15,6 +15,7 @@ using SixLabors.ImageSharp.Advanced;
"Bmp",
"Gif",
"Jpeg",
+ "Pbm",
"Png",
"Tga",
"Webp",
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs
deleted file mode 100644
index 90ebce3b87..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal abstract class Avx2JpegColorConverter : VectorizedJpegColorConverter
- {
- protected Avx2JpegColorConverter(JpegColorSpace colorSpace, int precision)
- : base(colorSpace, precision, 8)
- {
- }
-
- protected sealed override bool IsAvailable => SimdUtils.HasAvx2;
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs
deleted file mode 100644
index ed2e2cd762..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal abstract class BasicJpegColorConverter : JpegColorConverter
- {
- protected BasicJpegColorConverter(JpegColorSpace colorSpace, int precision)
- : base(colorSpace, precision)
- {
- }
-
- protected override bool IsAvailable => true;
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs
new file mode 100644
index 0000000000..7366ee30a9
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs
@@ -0,0 +1,52 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+#if SUPPORTS_RUNTIME_INTRINSICS
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
+{
+ internal abstract partial class JpegColorConverterBase
+ {
+ internal sealed class FromCmykAvx : JpegColorConverterAvx
+ {
+ public FromCmykAvx(int precision)
+ : base(JpegColorSpace.Cmyk, precision)
+ {
+ }
+
+ public override void ConvertToRgbInplace(in ComponentValues values)
+ {
+ ref Vector256 c0Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector256 c1Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector256 c2Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector256 c3Base =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ // Used for the color conversion
+ var scale = Vector256.Create(1 / (this.MaximumValue * this.MaximumValue));
+
+ nint n = values.Component0.Length / Vector256.Count;
+ for (nint i = 0; i < n; i++)
+ {
+ ref Vector256 c = ref Unsafe.Add(ref c0Base, i);
+ ref Vector256 m = ref Unsafe.Add(ref c1Base, i);
+ ref Vector256 y = ref Unsafe.Add(ref c2Base, i);
+ Vector256 k = Unsafe.Add(ref c3Base, i);
+
+ k = Avx.Multiply(k, scale);
+ c = Avx.Multiply(c, k);
+ m = Avx.Multiply(m, k);
+ y = Avx.Multiply(y, k);
+ }
+ }
+ }
+ }
+}
+#endif
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs
deleted file mode 100644
index 216c12735f..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-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;
-using static SixLabors.ImageSharp.SimdUtils;
-#endif
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal sealed class FromCmykAvx2 : Avx2JpegColorConverter
- {
- public FromCmykAvx2(int precision)
- : base(JpegColorSpace.Cmyk, precision)
- {
- }
-
- protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
- {
-#if SUPPORTS_RUNTIME_INTRINSICS
- ref Vector256 c0Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector256 c1Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector256 c2Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
- ref Vector256 c3Base =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
-
- // Used for the color conversion
- var scale = Vector256.Create(1 / this.MaximumValue);
-
- nint n = values.Component0.Length / 8;
- for (nint i = 0; i < n; i++)
- {
- ref Vector256 c = ref Unsafe.Add(ref c0Base, i);
- ref Vector256 m = ref Unsafe.Add(ref c1Base, i);
- ref Vector256 y = ref Unsafe.Add(ref c2Base, i);
- Vector256 k = Unsafe.Add(ref c3Base, i);
-
- k = Avx.Multiply(k, scale);
- c = Avx.Multiply(Avx.Multiply(c, k), scale);
- m = Avx.Multiply(Avx.Multiply(m, k), scale);
- y = Avx.Multiply(Avx.Multiply(y, k), scale);
- }
-#endif
- }
-
- protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykScalar.cs
similarity index 67%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykScalar.cs
index b0ad50301b..68dfa9bfba 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykScalar.cs
@@ -1,16 +1,15 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromCmykBasic : BasicJpegColorConverter
+ internal sealed class FromCmykScalar : JpegColorConverterScalar
{
- public FromCmykBasic(int precision)
+ public FromCmykScalar(int precision)
: base(JpegColorSpace.Cmyk, precision)
{
}
@@ -25,17 +24,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
Span c2 = values.Component2;
Span c3 = values.Component3;
- float scale = 1 / maxValue;
+ float scale = 1 / (maxValue * maxValue);
for (int i = 0; i < c0.Length; i++)
{
float c = c0[i];
float m = c1[i];
float y = c2[i];
- float k = c3[i] / maxValue;
+ float k = c3[i];
- c0[i] = c * k * scale;
- c1[i] = m * k * scale;
- c2[i] = y * k * scale;
+ k *= scale;
+ c0[i] = c * k;
+ c1[i] = m * k;
+ c2[i] = y * k;
}
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector.cs
new file mode 100644
index 0000000000..6b7ed169e3
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector.cs
@@ -0,0 +1,51 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
+{
+ internal abstract partial class JpegColorConverterBase
+ {
+ internal sealed class FromCmykVector : JpegColorConverterVector
+ {
+ public FromCmykVector(int precision)
+ : base(JpegColorSpace.Cmyk, precision)
+ {
+ }
+
+ protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
+ {
+ ref Vector cBase =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Vector mBase =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Vector yBase =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Vector kBase =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
+
+ var scale = new Vector(1 / (this.MaximumValue * this.MaximumValue));
+
+ nint n = values.Component0.Length / Vector.Count;
+ for (nint i = 0; i < n; i++)
+ {
+ ref Vector c = ref Unsafe.Add(ref cBase, i);
+ ref Vector m = ref Unsafe.Add(ref mBase, i);
+ ref Vector y = ref Unsafe.Add(ref yBase, i);
+ Vector k = Unsafe.Add(ref kBase, i);
+
+ k *= scale;
+ c *= k;
+ m *= k;
+ y *= k;
+ }
+ }
+
+ protected override void ConvertCoreInplace(in ComponentValues values) =>
+ FromCmykScalar.ConvertCoreInplace(values, this.MaximumValue);
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs
deleted file mode 100644
index 0da4c9ec23..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Tuples;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal sealed class FromCmykVector8 : Vector8JpegColorConverter
- {
- public FromCmykVector8(int precision)
- : base(JpegColorSpace.Cmyk, precision)
- {
- }
-
- protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
- {
- ref Vector cBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector mBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector yBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
- ref Vector kBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
-
- var scale = new Vector(1 / this.MaximumValue);
-
- // Walking 8 elements at one step:
- nint n = values.Component0.Length / 8;
- for (nint i = 0; i < n; i++)
- {
- ref Vector c = ref Unsafe.Add(ref cBase, i);
- ref Vector m = ref Unsafe.Add(ref mBase, i);
- ref Vector y = ref Unsafe.Add(ref yBase, i);
- Vector k = Unsafe.Add(ref kBase, i) * scale;
-
- c = (c * k) * scale;
- m = (m * k) * scale;
- y = (y * k) * scale;
- }
- }
-
- protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs
similarity index 59%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs
index eca6b62920..963543ad44 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs
@@ -1,47 +1,39 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Numerics;
+#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
-using static SixLabors.ImageSharp.SimdUtils;
-#endif
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromGrayscaleAvx2 : Avx2JpegColorConverter
+ internal sealed class FromGrayscaleAvx : JpegColorConverterAvx
{
- public FromGrayscaleAvx2(int precision)
+ public FromGrayscaleAvx(int precision)
: base(JpegColorSpace.Grayscale, precision)
{
}
- protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
+ public override void ConvertToRgbInplace(in ComponentValues values)
{
-#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256 c0Base =
ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
// Used for the color conversion
var scale = Vector256.Create(1 / this.MaximumValue);
- nint n = values.Component0.Length / 8;
+ nint n = values.Component0.Length / Vector256.Count;
for (nint i = 0; i < n; i++)
{
ref Vector256 c0 = ref Unsafe.Add(ref c0Base, i);
c0 = Avx.Multiply(c0, scale);
}
-#endif
}
-
- protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromGrayscaleBasic.ScaleValues(values.Component0, this.MaximumValue);
}
}
}
+#endif
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs
deleted file mode 100644
index 76d57bf069..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal sealed class FromGrayscaleBasic : BasicJpegColorConverter
- {
- public FromGrayscaleBasic(int precision)
- : base(JpegColorSpace.Grayscale, precision)
- {
- }
-
- public override void ConvertToRgbInplace(in ComponentValues values) =>
- ScaleValues(values.Component0, this.MaximumValue);
-
- internal static void ScaleValues(Span values, float maxValue)
- {
- Span vecValues = MemoryMarshal.Cast(values);
-
- var scaleVector = new Vector4(1 / maxValue);
-
- for (int i = 0; i < vecValues.Length; i++)
- {
- vecValues[i] *= scaleVector;
- }
-
- values = values.Slice(vecValues.Length * 4);
- if (!values.IsEmpty)
- {
- float scaleValue = 1f / maxValue;
- values[0] *= scaleValue;
-
- if ((uint)values.Length > 1)
- {
- values[1] *= scaleValue;
-
- if ((uint)values.Length > 2)
- {
- values[2] *= scaleValue;
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleScalar.cs
new file mode 100644
index 0000000000..3f6a6caa45
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleScalar.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
+{
+ internal abstract partial class JpegColorConverterBase
+ {
+ internal sealed class FromGrayscaleScalar : JpegColorConverterScalar
+ {
+ public FromGrayscaleScalar(int precision)
+ : base(JpegColorSpace.Grayscale, precision)
+ {
+ }
+
+ public override void ConvertToRgbInplace(in ComponentValues values) =>
+ ConvertCoreInplace(values.Component0, this.MaximumValue);
+
+ internal static void ConvertCoreInplace(Span values, float maxValue)
+ {
+ ref float valuesRef = ref MemoryMarshal.GetReference(values);
+ float scale = 1 / maxValue;
+
+ for (nint i = 0; i < values.Length; i++)
+ {
+ Unsafe.Add(ref valuesRef, i) *= scale;
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleVector.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleVector.cs
new file mode 100644
index 0000000000..c484aac28d
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleVector.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
+{
+ internal abstract partial class JpegColorConverterBase
+ {
+ internal sealed class FromGrayScaleVector : JpegColorConverterVector
+ {
+ public FromGrayScaleVector(int precision)
+ : base(JpegColorSpace.Grayscale, precision)
+ {
+ }
+
+ protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
+ {
+ ref Vector cBase =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+
+ var scale = new Vector(1 / this.MaximumValue);
+
+ nint n = values.Component0.Length / Vector.Count;
+ for (nint i = 0; i < n; i++)
+ {
+ ref Vector c0 = ref Unsafe.Add(ref cBase, i);
+ c0 *= scale;
+ }
+ }
+
+ protected override void ConvertCoreInplace(in ComponentValues values) =>
+ FromGrayscaleScalar.ConvertCoreInplace(values.Component0, this.MaximumValue);
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs
similarity index 53%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs
index 557e4e4173..f017716e3f 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs
@@ -1,40 +1,35 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Numerics;
+#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
-using static SixLabors.ImageSharp.SimdUtils;
-#endif
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromRgbAvx2 : Avx2JpegColorConverter
+ internal sealed class FromRgbAvx : JpegColorConverterAvx
{
- public FromRgbAvx2(int precision)
+ public FromRgbAvx(int precision)
: base(JpegColorSpace.RGB, precision)
{
}
- protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
+ public override void ConvertToRgbInplace(in ComponentValues values)
{
-#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256 rBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256 gBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector256 bBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2));
// Used for the color conversion
var scale = Vector256.Create(1 / this.MaximumValue);
- nint n = values.Component0.Length / 8;
+ nint n = values.Component0.Length / Vector256.Count;
for (nint i = 0; i < n; i++)
{
ref Vector256 r = ref Unsafe.Add(ref rBase, i);
@@ -44,11 +39,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
g = Avx.Multiply(g, scale);
b = Avx.Multiply(b, scale);
}
-#endif
}
-
- protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue);
}
}
}
+#endif
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs
deleted file mode 100644
index 1425e7b584..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using System.Runtime.InteropServices;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal sealed class FromRgbBasic : BasicJpegColorConverter
- {
- public FromRgbBasic(int precision)
- : base(JpegColorSpace.RGB, precision)
- {
- }
-
- public override void ConvertToRgbInplace(in ComponentValues values)
- {
- ConvertCoreInplace(values, this.MaximumValue);
- }
-
- internal static void ConvertCoreInplace(ComponentValues values, float maxValue)
- {
- FromGrayscaleBasic.ScaleValues(values.Component0, maxValue);
- FromGrayscaleBasic.ScaleValues(values.Component1, maxValue);
- FromGrayscaleBasic.ScaleValues(values.Component2, maxValue);
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbScalar.cs
new file mode 100644
index 0000000000..24c59206d8
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbScalar.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
+{
+ internal abstract partial class JpegColorConverterBase
+ {
+ internal sealed class FromRgbScalar : JpegColorConverterScalar
+ {
+ public FromRgbScalar(int precision)
+ : base(JpegColorSpace.RGB, precision)
+ {
+ }
+
+ public override void ConvertToRgbInplace(in ComponentValues values) =>
+ ConvertCoreInplace(values, this.MaximumValue);
+
+ internal static void ConvertCoreInplace(ComponentValues values, float maxValue)
+ {
+ FromGrayscaleScalar.ConvertCoreInplace(values.Component0, maxValue);
+ FromGrayscaleScalar.ConvertCoreInplace(values.Component1, maxValue);
+ FromGrayscaleScalar.ConvertCoreInplace(values.Component2, maxValue);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector.cs
similarity index 76%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector.cs
index a00361d970..ff3a2bee19 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector.cs
@@ -1,19 +1,17 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromRgbVector8 : Vector8JpegColorConverter
+ internal sealed class FromRgbVector : JpegColorConverterVector
{
- public FromRgbVector8(int precision)
+ public FromRgbVector(int precision)
: base(JpegColorSpace.RGB, precision)
{
}
@@ -29,8 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
var scale = new Vector(1 / this.MaximumValue);
- // Walking 8 elements at one step:
- nint n = values.Component0.Length / 8;
+ nint n = values.Component0.Length / Vector.Count;
for (nint i = 0; i < n; i++)
{
ref Vector r = ref Unsafe.Add(ref rBase, i);
@@ -43,7 +40,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue);
+ FromRgbScalar.ConvertCoreInplace(values, this.MaximumValue);
}
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs
similarity index 70%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs
index 5aae1faa27..892bcc79e1 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs
@@ -1,31 +1,27 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Numerics;
+#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static SixLabors.ImageSharp.SimdUtils;
-#endif
// ReSharper disable ImpureMethodCallOnReadonlyValueField
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromYCbCrAvx2 : Avx2JpegColorConverter
+ internal sealed class FromYCbCrAvx : JpegColorConverterAvx
{
- public FromYCbCrAvx2(int precision)
+ public FromYCbCrAvx(int precision)
: base(JpegColorSpace.YCbCr, precision)
{
}
- protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
+ public override void ConvertToRgbInplace(in ComponentValues values)
{
-#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256 c0Base =
ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256 c1Base =
@@ -36,18 +32,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// Used for the color conversion
var chromaOffset = Vector256.Create(-this.HalfValue);
var scale = Vector256.Create(1 / this.MaximumValue);
- var rCrMult = Vector256.Create(1.402F);
- var gCbMult = Vector256.Create(-0.344136F);
- var gCrMult = Vector256.Create(-0.714136F);
- var bCbMult = Vector256.Create(1.772F);
-
- // Used for packing.
- var va = Vector256.Create(1F);
- ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
- Vector256 vcontrol = Unsafe.As>(ref control);
+ var rCrMult = Vector256.Create(FromYCbCrScalar.RCrMult);
+ var gCbMult = Vector256.Create(-FromYCbCrScalar.GCbMult);
+ var gCrMult = Vector256.Create(-FromYCbCrScalar.GCrMult);
+ var bCbMult = Vector256.Create(FromYCbCrScalar.BCbMult);
// Walking 8 elements at one step:
- nint n = values.Component0.Length / 8;
+ nint n = values.Component0.Length / Vector256.Count;
for (nint i = 0; i < n; i++)
{
// y = yVals[i];
@@ -64,7 +55,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
- // Adding & multiplying 8 elements at one time:
Vector256 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult);
Vector256 g = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult);
Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult);
@@ -77,11 +67,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
c1 = g;
c2 = b;
}
-#endif
}
-
- protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}
+#endif
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs
deleted file mode 100644
index 990d29aa01..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal sealed class FromYCbCrBasic : BasicJpegColorConverter
- {
- public FromYCbCrBasic(int precision)
- : base(JpegColorSpace.YCbCr, precision)
- {
- }
-
- public override void ConvertToRgbInplace(in ComponentValues values)
- => ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
-
- internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue)
- {
- Span c0 = values.Component0;
- Span c1 = values.Component1;
- Span c2 = values.Component2;
-
- var scale = 1 / maxValue;
-
- for (int i = 0; i < c0.Length; i++)
- {
- float y = c0[i];
- float cb = c1[i] - halfValue;
- float cr = c2[i] - halfValue;
-
- c0[i] = MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero) * scale;
- c1[i] = MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero) * scale;
- c2[i] = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero) * scale;
- }
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrScalar.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrScalar.cs
new file mode 100644
index 0000000000..4b6d88f725
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrScalar.cs
@@ -0,0 +1,50 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
+{
+ internal abstract partial class JpegColorConverterBase
+ {
+ internal sealed class FromYCbCrScalar : JpegColorConverterScalar
+ {
+ // TODO: comments, derived from ITU-T Rec. T.871
+ internal const float RCrMult = 1.402f;
+ internal const float GCbMult = (float)(0.114 * 1.772 / 0.587);
+ internal const float GCrMult = (float)(0.299 * 1.402 / 0.587);
+ internal const float BCbMult = 1.772f;
+
+ public FromYCbCrScalar(int precision)
+ : base(JpegColorSpace.YCbCr, precision)
+ {
+ }
+
+ public override void ConvertToRgbInplace(in ComponentValues values)
+ => ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
+
+ internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue)
+ {
+ Span c0 = values.Component0;
+ Span c1 = values.Component1;
+ Span c2 = values.Component2;
+
+ float scale = 1 / maxValue;
+
+ for (int i = 0; i < c0.Length; i++)
+ {
+ float y = c0[i];
+ float cb = c1[i] - halfValue;
+ float cr = c2[i] - halfValue;
+
+ // r = y + (1.402F * cr);
+ // g = y - (0.344136F * cb) - (0.714136F * cr);
+ // b = y + (1.772F * cb);
+ c0[i] = MathF.Round(y + (RCrMult * cr), MidpointRounding.AwayFromZero) * scale;
+ c1[i] = MathF.Round(y - (GCbMult * cb) - (GCrMult * cr), MidpointRounding.AwayFromZero) * scale;
+ c2[i] = MathF.Round(y + (BCbMult * cb), MidpointRounding.AwayFromZero) * scale;
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector.cs
similarity index 73%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector.cs
index a077b9ed82..48e311d995 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector.cs
@@ -1,20 +1,18 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Tuples;
// ReSharper disable ImpureMethodCallOnReadonlyValueField
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromYCbCrVector8 : Vector8JpegColorConverter
+ internal sealed class FromYCbCrVector : JpegColorConverterVector
{
- public FromYCbCrVector8(int precision)
+ public FromYCbCrVector(int precision)
: base(JpegColorSpace.YCbCr, precision)
{
}
@@ -30,10 +28,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
var chromaOffset = new Vector(-this.HalfValue);
- // Walking 8 elements at one step:
- nint n = values.Component0.Length / 8;
var scale = new Vector(1 / this.MaximumValue);
+ var rCrMult = new Vector(FromYCbCrScalar.RCrMult);
+ var gCbMult = new Vector(-FromYCbCrScalar.GCbMult);
+ var gCrMult = new Vector(-FromYCbCrScalar.GCrMult);
+ var bCbMult = new Vector(FromYCbCrScalar.BCbMult);
+ nint n = values.Component0.Length / Vector.Count;
for (nint i = 0; i < n; i++)
{
// y = yVals[i];
@@ -49,10 +50,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
- // Adding & multiplying 8 elements at one time:
- Vector r = y + (cr * new Vector(1.402F));
- Vector g = y - (cb * new Vector(0.344136F)) - (cr * new Vector(0.714136F));
- Vector b = y + (cb * new Vector(1.772F));
+ Vector r = y + (cr * rCrMult);
+ Vector g = y + (cb * gCbMult) + (cr * gCrMult);
+ Vector b = y + (cb * bCbMult);
r = r.FastRound();
g = g.FastRound();
@@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
+ FromYCbCrScalar.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs
deleted file mode 100644
index 1ebc3e879d..0000000000
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Tuples;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
-{
- internal abstract partial class JpegColorConverter
- {
- internal sealed class FromYCbCrVector4 : VectorizedJpegColorConverter
- {
- public FromYCbCrVector4(int precision)
- : base(JpegColorSpace.YCbCr, precision, 8)
- {
- }
-
- protected override bool IsAvailable => SimdUtils.HasVector4;
-
- protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
- {
- DebugGuard.IsTrue(values.Component0.Length % 8 == 0, nameof(values), "Length should be divisible by 8!");
-
- ref Vector4Pair c0Base =
- ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component0));
- ref Vector4Pair c1Base =
- ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component1));
- ref Vector4Pair c2Base =
- ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component2));
-
- var chromaOffset = new Vector4(-this.HalfValue);
- var maxValue = this.MaximumValue;
-
- // Walking 8 elements at one step:
- nint n = values.Component0.Length / 8;
-
- for (nint i = 0; i < n; i++)
- {
- // y = yVals[i];
- ref Vector4Pair c0 = ref Unsafe.Add(ref c0Base, i);
-
- // cb = cbVals[i] - halfValue);
- ref Vector4Pair c1 = ref Unsafe.Add(ref c1Base, i);
- c1.AddInplace(chromaOffset);
-
- // cr = crVals[i] - halfValue;
- ref Vector4Pair c2 = ref Unsafe.Add(ref c2Base, i);
- c2.AddInplace(chromaOffset);
-
- // r = y + (1.402F * cr);
- Vector4Pair r = c0;
- Vector4Pair tmp = c2;
- tmp.MultiplyInplace(1.402F);
- r.AddInplace(ref tmp);
-
- // g = y - (0.344136F * cb) - (0.714136F * cr);
- Vector4Pair g = c0;
- tmp = c1;
- tmp.MultiplyInplace(-0.344136F);
- g.AddInplace(ref tmp);
- tmp = c2;
- tmp.MultiplyInplace(-0.714136F);
- g.AddInplace(ref tmp);
-
- // b = y + (1.772F * cb);
- Vector4Pair b = c0;
- tmp = c1;
- tmp.MultiplyInplace(1.772F);
- b.AddInplace(ref tmp);
-
- r.RoundAndDownscalePreVector8(maxValue);
- g.RoundAndDownscalePreVector8(maxValue);
- b.RoundAndDownscalePreVector8(maxValue);
-
- c0 = r;
- c1 = g;
- c2 = b;
- }
- }
-
- protected override void ConvertCoreInplace(in ComponentValues values)
- => FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs
similarity index 77%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs
index a3500a096a..1f18d5324d 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs
@@ -1,30 +1,26 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Numerics;
+#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static SixLabors.ImageSharp.SimdUtils;
-#endif
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromYccKAvx2 : Avx2JpegColorConverter
+ internal sealed class FromYccKAvx : JpegColorConverterAvx
{
- public FromYccKAvx2(int precision)
+ public FromYccKAvx(int precision)
: base(JpegColorSpace.Ycck, precision)
{
}
- protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
+ public override void ConvertToRgbInplace(in ComponentValues values)
{
-#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256 c0Base =
ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256 c1Base =
@@ -38,13 +34,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
var chromaOffset = Vector256.Create(-this.HalfValue);
var scale = Vector256.Create(1 / (this.MaximumValue * this.MaximumValue));
var max = Vector256.Create(this.MaximumValue);
- var rCrMult = Vector256.Create(1.402F);
- var gCbMult = Vector256.Create(-0.344136F);
- var gCrMult = Vector256.Create(-0.714136F);
- var bCbMult = Vector256.Create(1.772F);
+ var rCrMult = Vector256.Create(FromYCbCrScalar.RCrMult);
+ var gCbMult = Vector256.Create(-FromYCbCrScalar.GCbMult);
+ var gCrMult = Vector256.Create(-FromYCbCrScalar.GCrMult);
+ var bCbMult = Vector256.Create(FromYCbCrScalar.BCbMult);
// Walking 8 elements at one step:
- nint n = values.Component0.Length / 8;
+ nint n = values.Component0.Length / Vector256.Count;
for (nint i = 0; i < n; i++)
{
// y = yVals[i];
@@ -62,7 +58,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
- // Adding & multiplying 8 elements at one time:
Vector256 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult);
Vector256 g =
HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult);
@@ -80,11 +75,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
c1 = g;
c2 = b;
}
-#endif
}
-
- protected override void ConvertCoreInplace(in ComponentValues values) =>
- FromYccKBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}
+#endif
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKScalar.cs
similarity index 81%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKScalar.cs
index 4833f48683..d6387ae714 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKScalar.cs
@@ -1,16 +1,15 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromYccKBasic : BasicJpegColorConverter
+ internal sealed class FromYccKScalar : JpegColorConverterScalar
{
- public FromYccKBasic(int precision)
+ public FromYccKScalar(int precision)
: base(JpegColorSpace.Ycck, precision)
{
}
@@ -25,9 +24,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
Span c2 = values.Component2;
Span c3 = values.Component3;
- var v = new Vector4(0, 0, 0, 1F);
-
- var scale = 1 / (maxValue * maxValue);
+ float scale = 1 / (maxValue * maxValue);
for (int i = 0; i < values.Component0.Length; i++)
{
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector.cs
similarity index 71%
rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs
rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector.cs
index f830e5042c..66c79ae7c8 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector.cs
@@ -1,19 +1,17 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
-using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
- internal abstract partial class JpegColorConverter
+ internal abstract partial class JpegColorConverterBase
{
- internal sealed class FromYccKVector8 : Vector8JpegColorConverter
+ internal sealed class FromYccKVector : JpegColorConverterVector
{
- public FromYccKVector8(int precision)
+ public FromYccKVector(int precision)
: base(JpegColorSpace.Ycck, precision)
{
}
@@ -30,13 +28,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3));
var chromaOffset = new Vector(-this.HalfValue);
-
- // Walking 8 elements at one step:
- nint n = values.Component0.Length / 8;
-
+ var scale = new Vector(1 / (this.MaximumValue * this.MaximumValue));
var max = new Vector(this.MaximumValue);
- var scale = new Vector(1f) / (max * max);
+ var rCrMult = new Vector(FromYCbCrScalar.RCrMult);
+ var gCbMult = new Vector