From 8a7749644ab7b1170fc86194b400007885144678 Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Sat, 29 May 2021 21:19:36 +0300 Subject: [PATCH] Imporved internal rgb -> rcbcr conversion api for 420 subsampling --- .../Components/Encoder/HuffmanScanEncoder.cs | 10 +++--- .../Encoder/RgbToYCbCrConverterVectorized.cs | 36 ++++++++----------- .../Encoder/YCbCrForwardConverter{TPixel}.cs | 20 ++--------- 3 files changed, 21 insertions(+), 45 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index 3d99a1b95a..ff5ce957e0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -146,29 +146,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder int yOff = (i & 2) * 4; currentRows.Update(pixelBuffer, y + yOff); - pixelConverter.Convert420(frame, x + xOff, y + yOff, ref currentRows, ref temporalBlocks[0], i); + pixelConverter.Convert420(frame, x + xOff, y + yOff, ref currentRows, i); prevDCY = this.WriteBlock( QuantIndex.Luminance, prevDCY, - ref temporalBlocks[0], + ref pixelConverter.Y, ref luminanceQuantTable, ref unzig); } - pixelConverter.ConvertCbCr(ref temporalBlocks[0], ref temporalBlocks[1]); - prevDCCb = this.WriteBlock( QuantIndex.Chrominance, prevDCCb, - ref temporalBlocks[0], + ref pixelConverter.Cb, ref chrominanceQuantTable, ref unzig); prevDCCr = this.WriteBlock( QuantIndex.Chrominance, prevDCCr, - ref temporalBlocks[1], + ref pixelConverter.Cr, ref chrominanceQuantTable, ref unzig); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs index 9760e9e93c..055c7176a7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs @@ -126,12 +126,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// /// Total size of rgb span must be 200 bytes /// Span of rgb pixels with size of 64 - /// 8x8 destination matrix of Luminance(Y) converted data - /// - /// - /// - /// - public static void Convert420(ReadOnlySpan rgbSpan, ref Block8x8F yBlock, ref Block8x8F rAcc, ref Block8x8F gAcc, ref Block8x8F bAcc, int idx) + /// 8x8 destination matrix of Luminance(Y) converted dataф + public static void Convert420(ReadOnlySpan rgbSpan, ref Block8x8F yBlock, ref Block8x8F cbBlock, ref Block8x8F crBlock, int idx) { Debug.Assert(IsSupported, "AVX2 is required to run this converter"); @@ -152,9 +148,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder int destOffset = (idx & 2) * 4 + (idx & 1); - ref Vector128 destRedRef = ref Unsafe.Add(ref Unsafe.As>(ref rAcc), destOffset); - ref Vector128 destGreenRef = ref Unsafe.Add(ref Unsafe.As>(ref gAcc), destOffset); - ref Vector128 destBlueRef = ref Unsafe.Add(ref Unsafe.As>(ref bAcc), destOffset); + ref Vector128 destCbRef = ref Unsafe.Add(ref Unsafe.As>(ref cbBlock), destOffset); + ref Vector128 destCrRef = ref Unsafe.Add(ref Unsafe.As>(ref crBlock), destOffset); var extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveFirst24BytesToSeparateLanes)); var extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(ExtractRgb)); @@ -192,20 +187,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder int localDestOffset = (i & 1) * 4; - // red - Vector256 twoLane = Scale_8x4_4x2(rDataLanes); - Unsafe.Add(ref destRedRef, localDestOffset) = twoLane.GetLower(); - Unsafe.Add(ref destRedRef, localDestOffset + 2) = twoLane.GetUpper(); + r = Scale_8x4_4x2(rDataLanes); + g = Scale_8x4_4x2(gDataLanes); + b = Scale_8x4_4x2(bDataLanes); - // green - twoLane = Scale_8x4_4x2(gDataLanes); - Unsafe.Add(ref destGreenRef, localDestOffset) = twoLane.GetLower(); - Unsafe.Add(ref destGreenRef, localDestOffset + 2) = twoLane.GetUpper(); + // 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)) + Vector256 cb = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(f05, b), fn0331264, g), fn0168736, r)); + Unsafe.Add(ref destCbRef, localDestOffset) = cb.GetLower(); + Unsafe.Add(ref destCbRef, localDestOffset + 2) = cb.GetUpper(); - // blue - twoLane = Scale_8x4_4x2(bDataLanes); - Unsafe.Add(ref destBlueRef, localDestOffset) = twoLane.GetLower(); - Unsafe.Add(ref destBlueRef, localDestOffset + 2) = twoLane.GetUpper(); + // 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)) + Vector256 cr = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(fn0081312F, b), fn0418688, g), f05, r)); + Unsafe.Add(ref destCrRef, localDestOffset) = cr.GetLower(); + Unsafe.Add(ref destCrRef, localDestOffset + 2) = cr.GetUpper(); } #endif } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs index 7bf7b8547e..c835e8df81 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs @@ -88,19 +88,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// /// Converts a 8x8 image area inside 'pixels' at position (x,y) placing the result members of the structure (, , ) /// - public void Convert420(ImageFrame frame, int x, int y, ref RowOctet currentRows, ref Block8x8F yBlock, int idx) + public void Convert420(ImageFrame frame, int x, int y, ref RowOctet currentRows, int idx) { this.pixelBlock.LoadAndStretchEdges(frame.PixelBuffer, x, y, ref currentRows); PixelOperations.Instance.ToRgb24(frame.GetConfiguration(), this.pixelBlock.AsSpanUnsafe(), this.rgbSpan); - ref Block8x8F rSub = ref this.Y; - ref Block8x8F gSub = ref this.Cb; - ref Block8x8F bSub = ref this.Cr; - if (RgbToYCbCrConverterVectorized.IsSupported) { - RgbToYCbCrConverterVectorized.Convert420(this.rgbSpan, ref yBlock, ref rSub, ref gSub, ref bSub, idx); + RgbToYCbCrConverterVectorized.Convert420(this.rgbSpan, ref this.Y, ref this.Cb, ref this.Cr, idx); } else { @@ -108,17 +104,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder //this.colorTables.Convert(this.rgbSpan, ref yBlock, ref cbBlock, ref crBlock); } } - - public void ConvertCbCr(ref Block8x8F cb, ref Block8x8F cr) - { - if (RgbToYCbCrConverterVectorized.IsSupported) - { - RgbToYCbCrConverterVectorized.ConvertCbCr(ref this.Y, ref this.Cb, ref this.Cr, ref cb, ref cr); - } - else - { - throw new NotSupportedException("This is not yet implemented"); - } - } } }