mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
38 changed files with 1246 additions and 45 deletions
@ -0,0 +1,118 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using System.Numerics; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.ColorProfiles; |
|||
using SixLabors.ImageSharp.ColorProfiles.Icc; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
/// <summary>
|
|||
/// Color converter for tiff images, which use the jpeg compression and CMYK colorspace.
|
|||
/// </summary>
|
|||
internal sealed class TiffCmykScalar : JpegColorConverterScalar |
|||
{ |
|||
public TiffCmykScalar(int precision) |
|||
: base(JpegColorSpace.TiffCmyk, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlace(in ComponentValues values) |
|||
=> ConvertToRgbInPlace(in values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane); |
|||
|
|||
public static void ConvertToRgbInPlace(in ComponentValues values, float maxValue) |
|||
{ |
|||
Span<float> c0 = values.Component0; |
|||
Span<float> c1 = values.Component1; |
|||
Span<float> c2 = values.Component2; |
|||
Span<float> c3 = values.Component3; |
|||
|
|||
float scale = 1 / maxValue; |
|||
for (int i = 0; i < c0.Length; i++) |
|||
{ |
|||
float c = c0[i] * scale; |
|||
float m = c1[i] * scale; |
|||
float y = c2[i] * scale; |
|||
float k = 1 - (c3[i] * scale); |
|||
|
|||
c0[i] = (1 - c) * k; |
|||
c1[i] = (1 - m) * k; |
|||
c2[i] = (1 - y) * k; |
|||
} |
|||
} |
|||
|
|||
public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
Span<float> c = values.Component0; |
|||
Span<float> m = values.Component1; |
|||
Span<float> y = values.Component2; |
|||
Span<float> k = values.Component3; |
|||
|
|||
for (int i = 0; i < c.Length; i++) |
|||
{ |
|||
float ctmp = 255F - rLane[i]; |
|||
float mtmp = 255F - gLane[i]; |
|||
float ytmp = 255F - bLane[i]; |
|||
float ktmp = MathF.Min(MathF.Min(ctmp, mtmp), ytmp); |
|||
|
|||
if (ktmp >= 255F) |
|||
{ |
|||
ctmp = 0F; |
|||
mtmp = 0F; |
|||
ytmp = 0F; |
|||
} |
|||
else |
|||
{ |
|||
float divisor = 1 / (255F - ktmp); |
|||
ctmp = (ctmp - ktmp) * divisor; |
|||
mtmp = (mtmp - ktmp) * divisor; |
|||
ytmp = (ytmp - ktmp) * divisor; |
|||
} |
|||
|
|||
c[i] = ctmp * maxValue; |
|||
m[i] = mtmp * maxValue; |
|||
y[i] = ytmp * maxValue; |
|||
k[i] = ktmp; |
|||
} |
|||
} |
|||
|
|||
public static void ConvertToRgbInPlaceWithIcc(Configuration configuration, IccProfile profile, in ComponentValues values, float maxValue) |
|||
{ |
|||
using IMemoryOwner<float> memoryOwner = configuration.MemoryAllocator.Allocate<float>(values.Component0.Length * 4); |
|||
Span<float> packed = memoryOwner.Memory.Span; |
|||
|
|||
Span<float> c0 = values.Component0; |
|||
Span<float> c1 = values.Component1; |
|||
Span<float> c2 = values.Component2; |
|||
Span<float> c3 = values.Component3; |
|||
|
|||
PackedNormalizeInterleave4(c0, c1, c2, c3, packed, maxValue); |
|||
|
|||
Span<Cmyk> source = MemoryMarshal.Cast<float, Cmyk>(packed); |
|||
Span<Rgb> destination = MemoryMarshal.Cast<float, Rgb>(packed)[..source.Length]; |
|||
|
|||
ColorConversionOptions options = new() |
|||
{ |
|||
SourceIccProfile = profile, |
|||
TargetIccProfile = CompactSrgbV4Profile.Profile, |
|||
}; |
|||
ColorProfileConverter converter = new(options); |
|||
converter.Convert<Cmyk, Rgb>(source, destination); |
|||
|
|||
UnpackDeinterleave3(MemoryMarshal.Cast<float, Vector3>(packed)[..source.Length], c0, c1, c2); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
internal sealed class TiffCmykVector128 : JpegColorConverterVector128 |
|||
{ |
|||
public TiffCmykVector128(int precision) |
|||
: base(JpegColorSpace.TiffCmyk, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlace(in ComponentValues values) |
|||
{ |
|||
ref Vector128<float> c0Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector128<float> c1Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector128<float> c2Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector128<float> c3Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector128<float> scale = Vector128.Create(1 / this.MaximumValue); |
|||
|
|||
nuint n = values.Component0.Vector128Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
ref Vector128<float> c = ref Unsafe.Add(ref c0Base, i); |
|||
ref Vector128<float> m = ref Unsafe.Add(ref c1Base, i); |
|||
ref Vector128<float> y = ref Unsafe.Add(ref c2Base, i); |
|||
Vector128<float> k = Unsafe.Add(ref c3Base, i); |
|||
|
|||
k = Vector128<float>.One - (k * scale); |
|||
c = (Vector128<float>.One - (c * scale)) * k; |
|||
m = (Vector128<float>.One - (m * scale)) * k; |
|||
y = (Vector128<float>.One - (y * scale)) * k; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> TiffCmykScalar.ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane); |
|||
|
|||
public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
ref Vector128<float> destC = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector128<float> destM = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector128<float> destY = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector128<float> destK = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
ref Vector128<float> srcR = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(rLane)); |
|||
ref Vector128<float> srcG = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(gLane)); |
|||
ref Vector128<float> srcB = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(bLane)); |
|||
|
|||
Vector128<float> scale = Vector128.Create(maxValue); |
|||
|
|||
nuint n = values.Component0.Vector128Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
Vector128<float> ctmp = scale - Unsafe.Add(ref srcR, i); |
|||
Vector128<float> mtmp = scale - Unsafe.Add(ref srcG, i); |
|||
Vector128<float> ytmp = scale - Unsafe.Add(ref srcB, i); |
|||
Vector128<float> ktmp = Vector128.Min(ctmp, Vector128.Min(mtmp, ytmp)); |
|||
|
|||
Vector128<float> kMask = ~Vector128.Equals(ktmp, scale); |
|||
Vector128<float> divisor = Vector128<float>.One / (scale - ktmp); |
|||
|
|||
ctmp = ((ctmp - ktmp) * divisor) & kMask; |
|||
mtmp = ((mtmp - ktmp) * divisor) & kMask; |
|||
ytmp = ((ytmp - ktmp) * divisor) & kMask; |
|||
|
|||
Unsafe.Add(ref destC, i) = ctmp * scale; |
|||
Unsafe.Add(ref destM, i) = mtmp * scale; |
|||
Unsafe.Add(ref destY, i) = ytmp * scale; |
|||
Unsafe.Add(ref destK, i) = ktmp; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
internal sealed class TiffCmykVector256 : JpegColorConverterVector256 |
|||
{ |
|||
public TiffCmykVector256(int precision) |
|||
: base(JpegColorSpace.TiffCmyk, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlace(in ComponentValues values) |
|||
{ |
|||
ref Vector256<float> c0Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector256<float> c1Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector256<float> c2Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector256<float> c3Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector256<float> scale = Vector256.Create(1 / this.MaximumValue); |
|||
|
|||
nuint n = values.Component0.Vector256Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
ref Vector256<float> c = ref Unsafe.Add(ref c0Base, i); |
|||
ref Vector256<float> m = ref Unsafe.Add(ref c1Base, i); |
|||
ref Vector256<float> y = ref Unsafe.Add(ref c2Base, i); |
|||
Vector256<float> k = Unsafe.Add(ref c3Base, i); |
|||
|
|||
k = Vector256<float>.One - (k * scale); |
|||
c = (Vector256<float>.One - (c * scale)) * k; |
|||
m = (Vector256<float>.One - (m * scale)) * k; |
|||
y = (Vector256<float>.One - (y * scale)) * k; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> CmykScalar.ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> ConvertFromRgb(in values, this.MaximumValue, rLane, gLane, bLane); |
|||
|
|||
public static void ConvertFromRgb(in ComponentValues values, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
ref Vector256<float> destC = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector256<float> destM = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector256<float> destY = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector256<float> destK = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
ref Vector256<float> srcR = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(rLane)); |
|||
ref Vector256<float> srcG = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(gLane)); |
|||
ref Vector256<float> srcB = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(bLane)); |
|||
|
|||
Vector256<float> scale = Vector256.Create(maxValue); |
|||
|
|||
nuint n = values.Component0.Vector256Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
Vector256<float> ctmp = scale - Unsafe.Add(ref srcR, i); |
|||
Vector256<float> mtmp = scale - Unsafe.Add(ref srcG, i); |
|||
Vector256<float> ytmp = scale - Unsafe.Add(ref srcB, i); |
|||
Vector256<float> ktmp = Vector256.Min(ctmp, Vector256.Min(mtmp, ytmp)); |
|||
|
|||
Vector256<float> kMask = ~Vector256.Equals(ktmp, scale); |
|||
Vector256<float> divisor = Vector256<float>.One / (scale - ktmp); |
|||
|
|||
ctmp = ((ctmp - ktmp) * divisor) & kMask; |
|||
mtmp = ((mtmp - ktmp) * divisor) & kMask; |
|||
ytmp = ((ytmp - ktmp) * divisor) & kMask; |
|||
|
|||
Unsafe.Add(ref destC, i) = ctmp * scale; |
|||
Unsafe.Add(ref destM, i) = mtmp * scale; |
|||
Unsafe.Add(ref destY, i) = ytmp * scale; |
|||
Unsafe.Add(ref destK, i) = ktmp; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,108 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
internal sealed class TiffCmykVector512 : JpegColorConverterVector512 |
|||
{ |
|||
public TiffCmykVector512(int precision) |
|||
: base(JpegColorSpace.TiffCmyk, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> TiffCmykScalar.ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertToRgbInPlaceVectorized(in ComponentValues values) |
|||
{ |
|||
ref Vector512<float> c0Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector512<float> c1Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector512<float> c2Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector512<float> c3Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
// Used for the color conversion
|
|||
Vector512<float> scale = Vector512.Create(1 / this.MaximumValue); |
|||
|
|||
nuint n = values.Component0.Vector512Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
ref Vector512<float> c = ref Unsafe.Add(ref c0Base, i); |
|||
ref Vector512<float> m = ref Unsafe.Add(ref c1Base, i); |
|||
ref Vector512<float> y = ref Unsafe.Add(ref c2Base, i); |
|||
Vector512<float> k = Unsafe.Add(ref c3Base, i); |
|||
|
|||
k = Vector512<float>.One - (k * scale); |
|||
c = (Vector512<float>.One - (c * scale)) * k; |
|||
m = (Vector512<float>.One - (m * scale)) * k; |
|||
y = (Vector512<float>.One - (y * scale)) * k; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> ConvertFromRgbVectorized(in values, this.MaximumValue, rLane, gLane, bLane); |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) |
|||
=> TiffCmykScalar.ConvertToRgbInPlace(values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> TiffCmykScalar.ConvertFromRgb(values, this.MaximumValue, rLane, gLane, bLane); |
|||
|
|||
internal static void ConvertFromRgbVectorized(in ComponentValues values, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
ref Vector512<float> destC = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector512<float> destM = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector512<float> destY = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector512<float> destK = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
ref Vector512<float> srcR = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(rLane)); |
|||
ref Vector512<float> srcG = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(gLane)); |
|||
ref Vector512<float> srcB = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(bLane)); |
|||
|
|||
Vector512<float> scale = Vector512.Create(maxValue); |
|||
|
|||
nuint n = values.Component0.Vector512Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
Vector512<float> ctmp = scale - Unsafe.Add(ref srcR, i); |
|||
Vector512<float> mtmp = scale - Unsafe.Add(ref srcG, i); |
|||
Vector512<float> ytmp = scale - Unsafe.Add(ref srcB, i); |
|||
Vector512<float> ktmp = Vector512.Min(ctmp, Vector512.Min(mtmp, ytmp)); |
|||
|
|||
Vector512<float> kMask = ~Vector512.Equals(ktmp, scale); |
|||
Vector512<float> divisor = Vector512<float>.One / (scale - ktmp); |
|||
|
|||
ctmp = ((ctmp - ktmp) * divisor) & kMask; |
|||
mtmp = ((mtmp - ktmp) * divisor) & kMask; |
|||
ytmp = ((ytmp - ktmp) * divisor) & kMask; |
|||
|
|||
Unsafe.Add(ref destC, i) = ctmp * scale; |
|||
Unsafe.Add(ref destM, i) = mtmp * scale; |
|||
Unsafe.Add(ref destY, i) = ytmp * scale; |
|||
Unsafe.Add(ref destK, i) = ktmp; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,153 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using System.Numerics; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.ColorProfiles; |
|||
using SixLabors.ImageSharp.ColorProfiles.Icc; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
/// <summary>
|
|||
/// Color converter for tiff images, which use the jpeg compression and CMYK colorspace.
|
|||
/// </summary>
|
|||
internal sealed class TiffYccKScalar : JpegColorConverterScalar |
|||
{ |
|||
// 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 TiffYccKScalar(int precision) |
|||
: base(JpegColorSpace.TiffYccK, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlace(in ComponentValues values) |
|||
=> ConvertToRgbInPlace(in values, this.MaximumValue, this.HalfValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> ConvertFromRgb(values, this.HalfValue, this.MaximumValue, rLane, gLane, bLane); |
|||
|
|||
public static void ConvertToRgbInPlace(in ComponentValues values, float maxValue, float halfValue) |
|||
{ |
|||
Span<float> c0 = values.Component0; |
|||
Span<float> c1 = values.Component1; |
|||
Span<float> c2 = values.Component2; |
|||
Span<float> c3 = values.Component3; |
|||
|
|||
float scale = 1F / maxValue; |
|||
halfValue *= scale; |
|||
|
|||
for (int i = 0; i < values.Component0.Length; i++) |
|||
{ |
|||
float y = c0[i] * scale; |
|||
float cb = (c1[i] * scale) - halfValue; |
|||
float cr = (c2[i] * scale) - halfValue; |
|||
float scaledK = 1 - (c3[i] * scale); |
|||
|
|||
// r = y + (1.402F * cr);
|
|||
// g = y - (0.344136F * cb) - (0.714136F * cr);
|
|||
// b = y + (1.772F * cb);
|
|||
c0[i] = (y + (RCrMult * cr)) * scaledK; |
|||
c1[i] = (y - (GCbMult * cb) - (GCrMult * cr)) * scaledK; |
|||
c2[i] = (y + (BCbMult * cb)) * scaledK; |
|||
} |
|||
} |
|||
|
|||
public static void ConvertFromRgb(in ComponentValues values, float halfValue, float maxValue, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
Span<float> y = values.Component0; |
|||
Span<float> cb = values.Component1; |
|||
Span<float> cr = values.Component2; |
|||
Span<float> k = values.Component3; |
|||
|
|||
for (int i = 0; i < cr.Length; i++) |
|||
{ |
|||
// Scale down to [0-1]
|
|||
const float divisor = 1F / 255F; |
|||
float r = rLane[i] * divisor; |
|||
float g = gLane[i] * divisor; |
|||
float b = bLane[i] * divisor; |
|||
|
|||
float ytmp; |
|||
float cbtmp; |
|||
float crtmp; |
|||
float ktmp = 1F - MathF.Max(r, MathF.Max(g, b)); |
|||
|
|||
if (ktmp >= 1F) |
|||
{ |
|||
ytmp = 0F; |
|||
cbtmp = 0.5F; |
|||
crtmp = 0.5F; |
|||
ktmp = maxValue; |
|||
} |
|||
else |
|||
{ |
|||
float kmask = 1F / (1F - ktmp); |
|||
r *= kmask; |
|||
g *= kmask; |
|||
b *= kmask; |
|||
|
|||
// Scale to [0-maxValue]
|
|||
ytmp = ((0.299f * r) + (0.587f * g) + (0.114f * b)) * maxValue; |
|||
cbtmp = halfValue - (((0.168736f * r) - (0.331264f * g) + (0.5f * b)) * maxValue); |
|||
crtmp = halfValue + (((0.5f * r) - (0.418688f * g) - (0.081312f * b)) * maxValue); |
|||
ktmp *= maxValue; |
|||
} |
|||
|
|||
y[i] = ytmp; |
|||
cb[i] = cbtmp; |
|||
cr[i] = crtmp; |
|||
k[i] = ktmp; |
|||
} |
|||
} |
|||
|
|||
public static void ConvertToRgbInPlaceWithIcc(Configuration configuration, IccProfile profile, in ComponentValues values, float maxValue) |
|||
{ |
|||
using IMemoryOwner<float> memoryOwner = configuration.MemoryAllocator.Allocate<float>(values.Component0.Length * 4); |
|||
Span<float> packed = memoryOwner.Memory.Span; |
|||
|
|||
Span<float> c0 = values.Component0; |
|||
Span<float> c1 = values.Component1; |
|||
Span<float> c2 = values.Component2; |
|||
Span<float> c3 = values.Component3; |
|||
|
|||
PackedNormalizeInterleave4(c0, c1, c2, c3, packed, maxValue); |
|||
|
|||
ColorProfileConverter converter = new(); |
|||
Span<Cmyk> source = MemoryMarshal.Cast<float, Cmyk>(packed); |
|||
|
|||
// YccK is not a defined ICC color space — it's a JPEG-specific encoding used in Adobe-style CMYK JPEGs.
|
|||
// ICC profiles expect colorimetric CMYK values, so we must first convert YccK to CMYK using a hardcoded inverse transform.
|
|||
// This transform assumes Rec.601 YCbCr coefficients and an inverted K channel.
|
|||
//
|
|||
// The YccK => Cmyk conversion is independent of any embedded ICC profile.
|
|||
// Since the same RGB working space is used during conversion to and from XYZ,
|
|||
// colorimetric accuracy is preserved.
|
|||
converter.Convert<YccK, Cmyk>(MemoryMarshal.Cast<Cmyk, YccK>(source), source); |
|||
|
|||
Span<Rgb> destination = MemoryMarshal.Cast<float, Rgb>(packed)[..source.Length]; |
|||
|
|||
ColorConversionOptions options = new() |
|||
{ |
|||
SourceIccProfile = profile, |
|||
TargetIccProfile = CompactSrgbV4Profile.Profile, |
|||
}; |
|||
converter = new(options); |
|||
converter.Convert<Cmyk, Rgb>(source, destination); |
|||
|
|||
UnpackDeinterleave3(MemoryMarshal.Cast<float, Vector3>(packed)[..source.Length], c0, c1, c2); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using SixLabors.ImageSharp.Common.Helpers; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
internal sealed class TiffYccKVector128 : JpegColorConverterVector128 |
|||
{ |
|||
public TiffYccKVector128(int precision) |
|||
: base(JpegColorSpace.TiffYccK, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlace(in ComponentValues values) |
|||
{ |
|||
ref Vector128<float> c0Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector128<float> c1Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector128<float> c2Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector128<float> c3Base = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector128<float> scale = Vector128.Create(1F / this.MaximumValue); |
|||
Vector128<float> chromaOffset = Vector128.Create(this.HalfValue) * scale; |
|||
Vector128<float> rCrMult = Vector128.Create(YCbCrScalar.RCrMult); |
|||
Vector128<float> gCbMult = Vector128.Create(-YCbCrScalar.GCbMult); |
|||
Vector128<float> gCrMult = Vector128.Create(-YCbCrScalar.GCrMult); |
|||
Vector128<float> bCbMult = Vector128.Create(YCbCrScalar.BCbMult); |
|||
|
|||
nuint n = values.Component0.Vector128Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
ref Vector128<float> c0 = ref Unsafe.Add(ref c0Base, i); |
|||
ref Vector128<float> c1 = ref Unsafe.Add(ref c1Base, i); |
|||
ref Vector128<float> c2 = ref Unsafe.Add(ref c2Base, i); |
|||
ref Vector128<float> c3 = ref Unsafe.Add(ref c3Base, i); |
|||
|
|||
Vector128<float> y = c0 * scale; |
|||
Vector128<float> cb = (c1 * scale) - chromaOffset; |
|||
Vector128<float> cr = (c2 * scale) - chromaOffset; |
|||
Vector128<float> scaledK = Vector128<float>.One - (c3 * scale); |
|||
|
|||
// r = y + (1.402F * cr);
|
|||
// g = y - (0.344136F * cb) - (0.714136F * cr);
|
|||
// b = y + (1.772F * cb);
|
|||
Vector128<float> r = Vector128_.MultiplyAdd(y, cr, rCrMult) * scaledK; |
|||
Vector128<float> g = Vector128_.MultiplyAdd(Vector128_.MultiplyAdd(y, cb, gCbMult), cr, gCrMult) * scaledK; |
|||
Vector128<float> b = Vector128_.MultiplyAdd(y, cb, bCbMult) * scaledK; |
|||
|
|||
c0 = r; |
|||
c1 = g; |
|||
c2 = b; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> TiffYccKScalar.ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
ref Vector128<float> srcR = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(rLane)); |
|||
ref Vector128<float> srcG = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(gLane)); |
|||
ref Vector128<float> srcB = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(bLane)); |
|||
|
|||
ref Vector128<float> destY = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector128<float> destCb = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector128<float> destCr = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector128<float> destK = |
|||
ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector128<float> maxSourceValue = Vector128.Create(1 / 255F); |
|||
Vector128<float> maxSampleValue = Vector128.Create(this.MaximumValue); |
|||
Vector128<float> chromaOffset = Vector128.Create(this.HalfValue); |
|||
|
|||
Vector128<float> f0299 = Vector128.Create(0.299f); |
|||
Vector128<float> f0587 = Vector128.Create(0.587f); |
|||
Vector128<float> f0114 = Vector128.Create(0.114f); |
|||
Vector128<float> fn0168736 = Vector128.Create(-0.168736f); |
|||
Vector128<float> fn0331264 = Vector128.Create(-0.331264f); |
|||
Vector128<float> fn0418688 = Vector128.Create(-0.418688f); |
|||
Vector128<float> fn0081312F = Vector128.Create(-0.081312F); |
|||
Vector128<float> f05 = Vector128.Create(0.5f); |
|||
|
|||
nuint n = values.Component0.Vector128Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
Vector128<float> r = Unsafe.Add(ref srcR, i) * maxSourceValue; |
|||
Vector128<float> g = Unsafe.Add(ref srcG, i) * maxSourceValue; |
|||
Vector128<float> b = Unsafe.Add(ref srcB, i) * maxSourceValue; |
|||
Vector128<float> ktmp = Vector128<float>.One - Vector128.Max(r, Vector128.Min(g, b)); |
|||
|
|||
Vector128<float> kMask = ~Vector128.Equals(ktmp, Vector128<float>.One); |
|||
Vector128<float> divisor = Vector128<float>.One / (Vector128<float>.One - ktmp); |
|||
|
|||
r = (r * divisor) & kMask; |
|||
g = (g * divisor) & kMask; |
|||
b = (b * divisor) & kMask; |
|||
|
|||
// y = 0 + (0.299 * r) + (0.587 * g) + (0.114 * b)
|
|||
// cb = 128 - (0.168736 * r) - (0.331264 * g) + (0.5 * b)
|
|||
// cr = 128 + (0.5 * r) - (0.418688 * g) - (0.081312 * b)
|
|||
Vector128<float> y = Vector128_.MultiplyAdd(Vector128_.MultiplyAdd(f0114 * b, f0587, g), f0299, r); |
|||
Vector128<float> cb = chromaOffset + Vector128_.MultiplyAdd(Vector128_.MultiplyAdd(f05 * b, fn0331264, g), fn0168736, r); |
|||
Vector128<float> cr = chromaOffset + Vector128_.MultiplyAdd(Vector128_.MultiplyAdd(fn0081312F * b, fn0418688, g), f05, r); |
|||
|
|||
Unsafe.Add(ref destY, i) = y * maxSampleValue; |
|||
Unsafe.Add(ref destCb, i) = chromaOffset + (cb * maxSampleValue); |
|||
Unsafe.Add(ref destCr, i) = chromaOffset + (cr * maxSampleValue); |
|||
Unsafe.Add(ref destK, i) = ktmp * maxSampleValue; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,131 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using SixLabors.ImageSharp.Common.Helpers; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
internal sealed class TiffYccKVector256 : JpegColorConverterVector256 |
|||
{ |
|||
public TiffYccKVector256(int precision) |
|||
: base(JpegColorSpace.TiffYccK, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlace(in ComponentValues values) |
|||
{ |
|||
ref Vector256<float> c0Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector256<float> c1Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector256<float> c2Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector256<float> c3Base = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector256<float> scale = Vector256.Create(1F / this.MaximumValue); |
|||
Vector256<float> chromaOffset = Vector256.Create(this.HalfValue) * scale; |
|||
Vector256<float> rCrMult = Vector256.Create(YCbCrScalar.RCrMult); |
|||
Vector256<float> gCbMult = Vector256.Create(-YCbCrScalar.GCbMult); |
|||
Vector256<float> gCrMult = Vector256.Create(-YCbCrScalar.GCrMult); |
|||
Vector256<float> bCbMult = Vector256.Create(YCbCrScalar.BCbMult); |
|||
|
|||
nuint n = values.Component0.Vector256Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
ref Vector256<float> c0 = ref Unsafe.Add(ref c0Base, i); |
|||
ref Vector256<float> c1 = ref Unsafe.Add(ref c1Base, i); |
|||
ref Vector256<float> c2 = ref Unsafe.Add(ref c2Base, i); |
|||
ref Vector256<float> c3 = ref Unsafe.Add(ref c3Base, i); |
|||
|
|||
Vector256<float> y = c0 * scale; |
|||
Vector256<float> cb = (c1 * scale) - chromaOffset; |
|||
Vector256<float> cr = (c2 * scale) - chromaOffset; |
|||
Vector256<float> scaledK = Vector256<float>.One - (c3 * scale); |
|||
|
|||
// r = y + (1.402F * cr);
|
|||
// g = y - (0.344136F * cb) - (0.714136F * cr);
|
|||
// b = y + (1.772F * cb);
|
|||
Vector256<float> r = Vector256_.MultiplyAdd(y, cr, rCrMult) * scaledK; |
|||
Vector256<float> g = Vector256_.MultiplyAdd(Vector256_.MultiplyAdd(y, cb, gCbMult), cr, gCrMult) * scaledK; |
|||
Vector256<float> b = Vector256_.MultiplyAdd(y, cb, bCbMult) * scaledK; |
|||
|
|||
c0 = r; |
|||
c1 = g; |
|||
c2 = b; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> TiffYccKScalar.ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertFromRgb(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
ref Vector256<float> srcR = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(rLane)); |
|||
ref Vector256<float> srcG = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(gLane)); |
|||
ref Vector256<float> srcB = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(bLane)); |
|||
|
|||
ref Vector256<float> destY = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector256<float> destCb = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector256<float> destCr = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector256<float> destK = |
|||
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector256<float> maxSourceValue = Vector256.Create(255F); |
|||
Vector256<float> maxSampleValue = Vector256.Create(this.MaximumValue); |
|||
Vector256<float> chromaOffset = Vector256.Create(this.HalfValue); |
|||
|
|||
Vector256<float> f0299 = Vector256.Create(0.299f); |
|||
Vector256<float> f0587 = Vector256.Create(0.587f); |
|||
Vector256<float> f0114 = Vector256.Create(0.114f); |
|||
Vector256<float> fn0168736 = Vector256.Create(-0.168736f); |
|||
Vector256<float> fn0331264 = Vector256.Create(-0.331264f); |
|||
Vector256<float> fn0418688 = Vector256.Create(-0.418688f); |
|||
Vector256<float> fn0081312F = Vector256.Create(-0.081312F); |
|||
Vector256<float> f05 = Vector256.Create(0.5f); |
|||
|
|||
nuint n = values.Component0.Vector256Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
Vector256<float> r = Unsafe.Add(ref srcR, i) / maxSourceValue; |
|||
Vector256<float> g = Unsafe.Add(ref srcG, i) / maxSourceValue; |
|||
Vector256<float> b = Unsafe.Add(ref srcB, i) / maxSourceValue; |
|||
Vector256<float> ktmp = Vector256<float>.One - Vector256.Max(r, Vector256.Min(g, b)); |
|||
|
|||
Vector256<float> kMask = ~Vector256.Equals(ktmp, Vector256<float>.One); |
|||
Vector256<float> divisor = Vector256<float>.One / (Vector256<float>.One - ktmp); |
|||
|
|||
r = (r * divisor) & kMask; |
|||
g = (g * divisor) & kMask; |
|||
b = (b * divisor) & kMask; |
|||
|
|||
// y = 0 + (0.299 * r) + (0.587 * g) + (0.114 * b)
|
|||
// cb = 128 - (0.168736 * r) - (0.331264 * g) + (0.5 * b)
|
|||
// cr = 128 + (0.5 * r) - (0.418688 * g) - (0.081312 * b)
|
|||
Vector256<float> y = Vector256_.MultiplyAdd(Vector256_.MultiplyAdd(f0114 * b, f0587, g), f0299, r); |
|||
Vector256<float> cb = chromaOffset + Vector256_.MultiplyAdd(Vector256_.MultiplyAdd(f05 * b, fn0331264, g), fn0168736, r); |
|||
Vector256<float> cr = chromaOffset + Vector256_.MultiplyAdd(Vector256_.MultiplyAdd(fn0081312F * b, fn0418688, g), f05, r); |
|||
|
|||
Unsafe.Add(ref destY, i) = y * maxSampleValue; |
|||
Unsafe.Add(ref destCb, i) = chromaOffset + (cb * maxSampleValue); |
|||
Unsafe.Add(ref destCr, i) = chromaOffset + (cr * maxSampleValue); |
|||
Unsafe.Add(ref destK, i) = ktmp * maxSampleValue; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using System.Runtime.Intrinsics; |
|||
using SixLabors.ImageSharp.Common.Helpers; |
|||
using SixLabors.ImageSharp.Metadata.Profiles.Icc; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
|
|||
internal abstract partial class JpegColorConverterBase |
|||
{ |
|||
internal sealed class TiffYccKVector512 : JpegColorConverterVector512 |
|||
{ |
|||
public TiffYccKVector512(int precision) |
|||
: base(JpegColorSpace.TiffYccK, precision) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override void ConvertToRgbInPlaceWithIcc(Configuration configuration, in ComponentValues values, IccProfile profile) |
|||
=> TiffYccKScalar.ConvertToRgbInPlaceWithIcc(configuration, profile, values, this.MaximumValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertToRgbInPlaceVectorized(in ComponentValues values) |
|||
{ |
|||
ref Vector512<float> c0Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector512<float> c1Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector512<float> c2Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector512<float> c3Base = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector512<float> scale = Vector512.Create(1F / this.MaximumValue); |
|||
Vector512<float> chromaOffset = Vector512.Create(this.HalfValue) * scale; |
|||
Vector512<float> rCrMult = Vector512.Create(YCbCrScalar.RCrMult); |
|||
Vector512<float> gCbMult = Vector512.Create(-YCbCrScalar.GCbMult); |
|||
Vector512<float> gCrMult = Vector512.Create(-YCbCrScalar.GCrMult); |
|||
Vector512<float> bCbMult = Vector512.Create(YCbCrScalar.BCbMult); |
|||
|
|||
nuint n = values.Component0.Vector512Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
ref Vector512<float> c0 = ref Unsafe.Add(ref c0Base, i); |
|||
ref Vector512<float> c1 = ref Unsafe.Add(ref c1Base, i); |
|||
ref Vector512<float> c2 = ref Unsafe.Add(ref c2Base, i); |
|||
ref Vector512<float> c3 = ref Unsafe.Add(ref c3Base, i); |
|||
|
|||
Vector512<float> y = c0 * scale; |
|||
Vector512<float> cb = (c1 * scale) - chromaOffset; |
|||
Vector512<float> cr = (c2 * scale) - chromaOffset; |
|||
Vector512<float> scaledK = Vector512<float>.One - (c3 * scale); |
|||
|
|||
// r = y + (1.402F * cr);
|
|||
// g = y - (0.344136F * cb) - (0.714136F * cr);
|
|||
// b = y + (1.772F * cb);
|
|||
Vector512<float> r = Vector512_.MultiplyAdd(y, cr, rCrMult) * scaledK; |
|||
Vector512<float> g = Vector512_.MultiplyAdd(Vector512_.MultiplyAdd(y, cb, gCbMult), cr, gCrMult) * scaledK; |
|||
Vector512<float> b = Vector512_.MultiplyAdd(y, cb, bCbMult) * scaledK; |
|||
|
|||
c0 = r; |
|||
c1 = g; |
|||
c2 = b; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertFromRgbVectorized(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> ConvertFromRgbVectorized(in values, this.MaximumValue, this.HalfValue, rLane, gLane, bLane); |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertToRgbInPlaceScalarRemainder(in ComponentValues values) |
|||
=> TiffYccKScalar.ConvertToRgbInPlace(values, this.MaximumValue, this.HalfValue); |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void ConvertFromRgbScalarRemainder(in ComponentValues values, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
=> TiffYccKScalar.ConvertFromRgb(values, this.HalfValue, this.MaximumValue, rLane, gLane, bLane); |
|||
|
|||
internal static void ConvertFromRgbVectorized(in ComponentValues values, float maxValue, float halfValue, Span<float> rLane, Span<float> gLane, Span<float> bLane) |
|||
{ |
|||
ref Vector512<float> srcR = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(rLane)); |
|||
ref Vector512<float> srcG = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(gLane)); |
|||
ref Vector512<float> srcB = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(bLane)); |
|||
|
|||
ref Vector512<float> destY = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component0)); |
|||
ref Vector512<float> destCb = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component1)); |
|||
ref Vector512<float> destCr = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component2)); |
|||
ref Vector512<float> destK = |
|||
ref Unsafe.As<float, Vector512<float>>(ref MemoryMarshal.GetReference(values.Component3)); |
|||
|
|||
Vector512<float> maxSourceValue = Vector512.Create(255F); |
|||
Vector512<float> maxSampleValue = Vector512.Create(maxValue); |
|||
Vector512<float> chromaOffset = Vector512.Create(halfValue); |
|||
|
|||
Vector512<float> f0299 = Vector512.Create(0.299f); |
|||
Vector512<float> f0587 = Vector512.Create(0.587f); |
|||
Vector512<float> f0114 = Vector512.Create(0.114f); |
|||
Vector512<float> fn0168736 = Vector512.Create(-0.168736f); |
|||
Vector512<float> fn0331264 = Vector512.Create(-0.331264f); |
|||
Vector512<float> fn0418688 = Vector512.Create(-0.418688f); |
|||
Vector512<float> fn0081312F = Vector512.Create(-0.081312F); |
|||
Vector512<float> f05 = Vector512.Create(0.5f); |
|||
|
|||
nuint n = values.Component0.Vector512Count<float>(); |
|||
for (nuint i = 0; i < n; i++) |
|||
{ |
|||
Vector512<float> r = Unsafe.Add(ref srcR, i) / maxSourceValue; |
|||
Vector512<float> g = Unsafe.Add(ref srcG, i) / maxSourceValue; |
|||
Vector512<float> b = Unsafe.Add(ref srcB, i) / maxSourceValue; |
|||
Vector512<float> ktmp = Vector512<float>.One - Vector512.Max(r, Vector512.Min(g, b)); |
|||
|
|||
Vector512<float> kMask = ~Vector512.Equals(ktmp, Vector512<float>.One); |
|||
Vector512<float> divisor = Vector512<float>.One / (Vector512<float>.One - ktmp); |
|||
|
|||
r = (r * divisor) & kMask; |
|||
g = (g * divisor) & kMask; |
|||
b = (b * divisor) & kMask; |
|||
|
|||
// y = 0 + (0.299 * r) + (0.587 * g) + (0.114 * b)
|
|||
// cb = 128 - (0.168736 * r) - (0.331264 * g) + (0.5 * b)
|
|||
// cr = 128 + (0.5 * r) - (0.418688 * g) - (0.081312 * b)
|
|||
Vector512<float> y = Vector512_.MultiplyAdd(Vector512_.MultiplyAdd(f0114 * b, f0587, g), f0299, r); |
|||
Vector512<float> cb = chromaOffset + Vector512_.MultiplyAdd(Vector512_.MultiplyAdd(f05 * b, fn0331264, g), fn0168736, r); |
|||
Vector512<float> cr = chromaOffset + Vector512_.MultiplyAdd(Vector512_.MultiplyAdd(fn0081312F * b, fn0418688, g), f05, r); |
|||
|
|||
Unsafe.Add(ref destY, i) = y * maxSampleValue; |
|||
Unsafe.Add(ref destCb, i) = chromaOffset + (cb * maxSampleValue); |
|||
Unsafe.Add(ref destCr, i) = chromaOffset + (cr * maxSampleValue); |
|||
Unsafe.Add(ref destK, i) = ktmp * maxSampleValue; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:7f68db78d765a7f36570cd7b57a1f06cfca24c3b4916d0692a4aa051209ec327 |
|||
size 616 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:c4f77673028643af0ac02a8f6a1e2db14052177e3401c369391a8ff7e943770c |
|||
size 7679254 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:e616895c21fd8b19a216e8a3ef4968bd413589b5875efdac29860f019a710527 |
|||
size 7517284 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:d7911e059049c427229136479740fd62e2e09907549ec3e1421a6a60da6167cc |
|||
size 7840892 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:291f2033a7b4cfc10fb3301283c167b3fbc288bc173c95b21bc726bf076865af |
|||
size 7649213 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:abb923e457acc31a7f18c46a7d58fc5a42f5c3d197236403921e3ee623fa4fac |
|||
size 2046 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:abb923e457acc31a7f18c46a7d58fc5a42f5c3d197236403921e3ee623fa4fac |
|||
size 2046 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:868fbf7fc7a61bc6b1226160c8dc3bb1faebd8d4a2a6fe9494962f3fbe3a7fdc |
|||
size 5024256 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:867851192f540742ba1481f503834f8aa77caa03ac59f8204d098bf940b0bb3a |
|||
size 4387646 |
|||
Loading…
Reference in new issue