mirror of https://github.com/SixLabors/ImageSharp
3 changed files with 70 additions and 1 deletions
@ -0,0 +1,67 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Processing.RenderPipeline; |
|||
|
|||
/// <summary>
|
|||
/// SIMD-based conversion from Y'Cb'Cr to RGB pixel buffers.
|
|||
/// </summary>
|
|||
internal sealed class YCbCrStage : RenderPipelineStageBase |
|||
{ |
|||
public YCbCrStage(Configuration configuration) |
|||
: base(configuration) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string Name => "YCbCr"; |
|||
|
|||
/// <inheritdoc />
|
|||
public override void ProcessRow(Buffer2D<Memory<float>> inputRows, Buffer2D<Memory<float>> outputRows, int xExtraLeft, int xExtraRight, int width, int xPos, int yPos) |
|||
{ |
|||
// Vectors for conversion, defined by the ITU
|
|||
Vector<float> c128 = Vector.Create(128.0f / 255); |
|||
Vector<float> crcr = Vector.Create(1.402f); |
|||
Vector<float> cgcb = Vector.Create(-0.114f * 1.772f / 0.587f); |
|||
Vector<float> cgcr = Vector.Create(-0.299f * 1.402f / 0.587f); |
|||
Vector<float> cbcb = Vector.Create(1.772f); |
|||
|
|||
Span<float> row0 = this.GetInputRow(inputRows, 0, 0); |
|||
Span<float> row1 = this.GetInputRow(inputRows, 1, 0); |
|||
Span<float> row2 = this.GetInputRow(inputRows, 2, 0); |
|||
|
|||
// Using refs for better performance
|
|||
ref float row0Ref = ref MemoryMarshal.GetReference(row0); |
|||
ref float row1Ref = ref MemoryMarshal.GetReference(row1); |
|||
ref float row2Ref = ref MemoryMarshal.GetReference(row2); |
|||
|
|||
for (int x = 0; x < width; x += Vector<float>.Count) |
|||
{ |
|||
// Y'Cb'Cr input vectors
|
|||
Vector<float> yVec = Vector.LoadUnsafe(ref Unsafe.Add(ref row1Ref, x)) + c128; |
|||
Vector<float> cbVec = Vector.LoadUnsafe(ref Unsafe.Add(ref row0Ref, x)); |
|||
Vector<float> crVec = Vector.LoadUnsafe(ref Unsafe.Add(ref row2Ref, x)); |
|||
|
|||
// RGB output vectors
|
|||
Vector<float> rVec = (crcr * crVec) + yVec; |
|||
Vector<float> gVec = (cgcr * crVec) + ((cgcb * cbVec) + yVec); |
|||
Vector<float> bVec = (cbcb * cbVec) + yVec; |
|||
|
|||
// Copying to the output...
|
|||
rVec.StoreUnsafe(ref Unsafe.Add(ref row0Ref, x)); |
|||
gVec.StoreUnsafe(ref Unsafe.Add(ref row1Ref, x)); |
|||
bVec.StoreUnsafe(ref Unsafe.Add(ref row2Ref, x)); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override RenderPipelineChannelMode GetChannelMode(int channel) => |
|||
channel < 3 |
|||
? RenderPipelineChannelMode.InPlace |
|||
: RenderPipelineChannelMode.Ignored; |
|||
} |
|||
Loading…
Reference in new issue