From 078703b595ecf204db96c34220b1d23ca9499b8a Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Fri, 4 Jun 2021 17:28:57 +0300 Subject: [PATCH] Added docs, renamed LuT converter for 444 and 420 subsampling methods, added debug guards --- .../Encoder/RgbToYCbCrConverterLut.cs | 32 +++++++++++++++---- .../YCbCrForwardConverter420{TPixel}.cs | 2 +- .../YCbCrForwardConverter444{TPixel}.cs | 2 +- .../Encoder/YCbCrForwardConverterBenchmark.cs | 2 +- .../Formats/Jpg/RgbToYCbCrConverterTests.cs | 2 +- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterLut.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterLut.cs index 18f5ee0e70..3706b80622 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterLut.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterLut.cs @@ -142,8 +142,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder crResult = (this.CbBTable[r] + this.CrGTable[g] + this.CrBTable[b]) >> ScaleBits; } - - public void Convert(Span rgbSpan, ref Block8x8F yBlock, ref Block8x8F cbBlock, ref Block8x8F crBlock) + /// + /// Converts Rgb24 pixels into YCbCr color space with 4:4:4 subsampling sampling of luminance and chroma. + /// + /// Span of Rgb24 pixel data + /// Resulting Y values block + /// Resulting Cb values block + /// Resulting Cr values block + public void Convert444(Span rgbSpan, ref Block8x8F yBlock, ref Block8x8F cbBlock, ref Block8x8F crBlock) { ref Rgb24 rgbStart = ref rgbSpan[0]; @@ -162,8 +168,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder } } - public void Convert(Span rgbSpan, ref Block8x8F yBlockLeft, ref Block8x8F yBlockRight, ref Block8x8F cbBlock, ref Block8x8F crBlock, int row) + /// + /// Converts Rgb24 pixels into YCbCr color space with 4:2:0 subsampling of luminance and chroma. + /// + /// Calculates 2 out of 4 luminance blocks and half of chroma blocks. This method must be called twice per 4x 8x8 DCT blocks with different row param. + /// Span of Rgb24 pixel data + /// First or "left" resulting Y block + /// Second or "right" resulting Y block + /// Resulting Cb values block + /// Resulting Cr values block + /// Row index of the 16x16 block, 0 or 1 + public void Convert420(Span rgbSpan, ref Block8x8F yBlockLeft, ref Block8x8F yBlockRight, ref Block8x8F cbBlock, ref Block8x8F crBlock, int row) { + DebugGuard.MustBeBetweenOrEqualTo(row, 0, 1, nameof(row)); + ref float yBlockLeftRef = ref Unsafe.As(ref yBlockLeft); ref float yBlockRightRef = ref Unsafe.As(ref yBlockRight); @@ -189,9 +207,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder ref float yBlockRef = ref Unsafe.Add(ref yBlockLeftRef, (i + j) * 8 + k); Rgb24 px0 = Unsafe.Add(ref stride, k); - this.ConvertPixelInto(px0.R, px0.G, px0.B, ref yBlockRef); - Rgb24 px1 = Unsafe.Add(ref stride, k + 1); + + this.ConvertPixelInto(px0.R, px0.G, px0.B, ref yBlockRef); this.ConvertPixelInto(px1.R, px1.G, px1.B, ref Unsafe.Add(ref yBlockRef, 1)); int idx = 3 * (k / 2); @@ -207,9 +225,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder ref float yBlockRef = ref Unsafe.Add(ref yBlockRightRef, (i + j) * 8 + k); Rgb24 px0 = Unsafe.Add(ref stride, k); - this.ConvertPixelInto(px0.R, px0.G, px0.B, ref yBlockRef); - Rgb24 px1 = Unsafe.Add(ref stride, k + 1); + + this.ConvertPixelInto(px0.R, px0.G, px0.B, ref yBlockRef); this.ConvertPixelInto(px1.R, px1.G, px1.B, ref Unsafe.Add(ref yBlockRef, 1)); int idx = 3 * (4 + (k / 2)); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter420{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter420{TPixel}.cs index 2e8433cdc6..e0e7854b0d 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter420{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter420{TPixel}.cs @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder } else { - this.colorTables.Convert(this.rgbSpan, ref this.YLeft, ref this.YRight, ref this.Cb, ref this.Cr, idx); + this.colorTables.Convert420(this.rgbSpan, ref this.YLeft, ref this.YRight, ref this.Cb, ref this.Cr, idx); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs index 27f7e3ae9c..f3ae339347 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs @@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder } else { - this.colorTables.Convert(this.rgbSpan, ref yBlock, ref cbBlock, ref crBlock); + this.colorTables.Convert444(this.rgbSpan, ref yBlock, ref cbBlock, ref crBlock); } } } diff --git a/tests/ImageSharp.Benchmarks/Format/Jpeg/Components/Encoder/YCbCrForwardConverterBenchmark.cs b/tests/ImageSharp.Benchmarks/Format/Jpeg/Components/Encoder/YCbCrForwardConverterBenchmark.cs index 1db4072932..60a5853847 100644 --- a/tests/ImageSharp.Benchmarks/Format/Jpeg/Components/Encoder/YCbCrForwardConverterBenchmark.cs +++ b/tests/ImageSharp.Benchmarks/Format/Jpeg/Components/Encoder/YCbCrForwardConverterBenchmark.cs @@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Format.Jpeg.Components.Encoder Block8x8F cb = default; Block8x8F cr = default; - this.converter.Convert(this.data.AsSpan(), ref y, ref cb, ref cr); + this.converter.Convert444(this.data.AsSpan(), ref y, ref cb, ref cr); } [Benchmark] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs index 9a6fc8d6fd..c605a6cf89 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Block8x8F cb = default; Block8x8F cr = default; - target.Convert(data.AsSpan(), ref y, ref cb, ref cr); + target.Convert444(data.AsSpan(), ref y, ref cb, ref cr); Verify(data, ref y, ref cb, ref cr, new ApproximateColorSpaceComparer(1F)); }