diff --git a/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/Epf1Stage.cs b/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/Epf1Stage.cs
index b42513898c..5dc19b6626 100644
--- a/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/Epf1Stage.cs
+++ b/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/Epf1Stage.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Formats.Jxl.Processing.RenderPipeline;
///
/// Edge Preserving Filter (type 1) stage.
///
-internal class Epf1Stage : RenderPipelineStageBase
+internal sealed class Epf1Stage : RenderPipelineStageBase
{
private readonly JxlLoopFilter loopFilter;
private readonly JxlImageF sigma;
diff --git a/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/WriteToOutputStage.cs b/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/WriteToOutputStage.cs
index e07be6ec06..ad790ed10a 100644
--- a/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/WriteToOutputStage.cs
+++ b/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/WriteToOutputStage.cs
@@ -1,8 +1,10 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
+using System.Numerics;
using SixLabors.ImageSharp.Formats.Jxl.IO.Metadata;
using SixLabors.ImageSharp.Formats.Jxl.Processing.Image;
+using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jxl.Processing.RenderPipeline;
diff --git a/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/YCbCrStage.cs b/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/YCbCrStage.cs
new file mode 100644
index 0000000000..6de34c61bf
--- /dev/null
+++ b/src/ImageSharp/Formats/Jxl/Processing/RenderPipeline/YCbCrStage.cs
@@ -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;
+
+///
+/// SIMD-based conversion from Y'Cb'Cr to RGB pixel buffers.
+///
+internal sealed class YCbCrStage : RenderPipelineStageBase
+{
+ public YCbCrStage(Configuration configuration)
+ : base(configuration)
+ {
+ }
+
+ ///
+ public override string Name => "YCbCr";
+
+ ///
+ public override void ProcessRow(Buffer2D> inputRows, Buffer2D> outputRows, int xExtraLeft, int xExtraRight, int width, int xPos, int yPos)
+ {
+ // Vectors for conversion, defined by the ITU
+ Vector c128 = Vector.Create(128.0f / 255);
+ Vector crcr = Vector.Create(1.402f);
+ Vector cgcb = Vector.Create(-0.114f * 1.772f / 0.587f);
+ Vector cgcr = Vector.Create(-0.299f * 1.402f / 0.587f);
+ Vector cbcb = Vector.Create(1.772f);
+
+ Span row0 = this.GetInputRow(inputRows, 0, 0);
+ Span row1 = this.GetInputRow(inputRows, 1, 0);
+ Span 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.Count)
+ {
+ // Y'Cb'Cr input vectors
+ Vector yVec = Vector.LoadUnsafe(ref Unsafe.Add(ref row1Ref, x)) + c128;
+ Vector cbVec = Vector.LoadUnsafe(ref Unsafe.Add(ref row0Ref, x));
+ Vector crVec = Vector.LoadUnsafe(ref Unsafe.Add(ref row2Ref, x));
+
+ // RGB output vectors
+ Vector rVec = (crcr * crVec) + yVec;
+ Vector gVec = (cgcr * crVec) + ((cgcb * cbVec) + yVec);
+ Vector 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));
+ }
+ }
+
+ ///
+ public override RenderPipelineChannelMode GetChannelMode(int channel) =>
+ channel < 3
+ ? RenderPipelineChannelMode.InPlace
+ : RenderPipelineChannelMode.Ignored;
+}